mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 06:42:03 +00:00
docs: map existing codebase
- STACK.md - Technologies and dependencies - ARCHITECTURE.md - System design and patterns - STRUCTURE.md - Directory layout - CONVENTIONS.md - Code style and patterns - TESTING.md - Test structure - INTEGRATIONS.md - External services - CONCERNS.md - Technical debt and issues
This commit is contained in:
234
.planning/codebase/ARCHITECTURE.md
Normal file
234
.planning/codebase/ARCHITECTURE.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# Architecture
|
||||
|
||||
**Analysis Date:** 2026-01-27
|
||||
|
||||
## Pattern Overview
|
||||
|
||||
**Overall:** Monorepo with layered client-server architecture (Electron-first) and pluggable provider abstraction for AI models.
|
||||
|
||||
**Key Characteristics:**
|
||||
|
||||
- Event-driven communication via WebSocket between frontend and backend
|
||||
- Multi-provider AI model abstraction layer (Claude, Cursor, Codex, Gemini, OpenCode, Copilot)
|
||||
- Feature-centric workflow stored in `.automaker/` directories
|
||||
- Isolated git worktree execution for each feature
|
||||
- State management through Zustand stores with API persistence
|
||||
|
||||
## Layers
|
||||
|
||||
**Presentation Layer (UI):**
|
||||
|
||||
- Purpose: React 19 Electron/web frontend with TanStack Router file-based routing
|
||||
- Location: `apps/ui/src/`
|
||||
- Contains: Route components, view pages, custom React hooks, Zustand stores, API client
|
||||
- Depends on: @automaker/types, @automaker/utils, HTTP API backend
|
||||
- Used by: Electron main process (desktop), web browser (web mode)
|
||||
|
||||
**API Layer (Server):**
|
||||
|
||||
- Purpose: Express 5 backend exposing RESTful and WebSocket endpoints
|
||||
- Location: `apps/server/src/`
|
||||
- Contains: Route handlers, business logic services, middleware, provider adapters
|
||||
- Depends on: @automaker/types, @automaker/utils, @automaker/platform, Claude Agent SDK
|
||||
- Used by: UI frontend via HTTP/WebSocket
|
||||
|
||||
**Service Layer (Server):**
|
||||
|
||||
- Purpose: Business logic and domain operations
|
||||
- Location: `apps/server/src/services/`
|
||||
- Contains: AgentService, FeatureLoader, AutoModeService, SettingsService, DevServerService, etc.
|
||||
- Depends on: Providers, secure filesystem, feature storage
|
||||
- Used by: Route handlers
|
||||
|
||||
**Provider Abstraction (Server):**
|
||||
|
||||
- Purpose: Unified interface for different AI model providers
|
||||
- Location: `apps/server/src/providers/`
|
||||
- Contains: ProviderFactory, specific provider implementations (ClaudeProvider, CursorProvider, CodexProvider, GeminiProvider, OpencodeProvider, CopilotProvider)
|
||||
- Depends on: @automaker/types, provider SDKs
|
||||
- Used by: AgentService
|
||||
|
||||
**Shared Library Layer:**
|
||||
|
||||
- Purpose: Type definitions and utilities shared across apps
|
||||
- Location: `libs/`
|
||||
- Contains: @automaker/types, @automaker/utils, @automaker/platform, @automaker/prompts, @automaker/model-resolver, @automaker/dependency-resolver, @automaker/git-utils, @automaker/spec-parser
|
||||
- Depends on: None (types has no external deps)
|
||||
- Used by: All apps and services
|
||||
|
||||
## Data Flow
|
||||
|
||||
**Feature Execution Flow:**
|
||||
|
||||
1. User creates/updates feature via UI (`apps/ui/src/`)
|
||||
2. UI sends HTTP request to backend (`POST /api/features`)
|
||||
3. Server route handler invokes FeatureLoader to persist to `.automaker/features/{featureId}/`
|
||||
4. When executing, AgentService loads feature, creates isolated git worktree via @automaker/git-utils
|
||||
5. AgentService invokes ProviderFactory to get appropriate AI provider (Claude, Cursor, etc.)
|
||||
6. Provider executes with context from CLAUDE.md files via @automaker/utils loadContextFiles()
|
||||
7. Server emits events via EventEmitter throughout execution
|
||||
8. Events stream to frontend via WebSocket
|
||||
9. UI updates stores and renders real-time progress
|
||||
10. Feature results persist back to `.automaker/features/` with generated agent-output.md
|
||||
|
||||
**State Management:**
|
||||
|
||||
**Frontend State (Zustand):**
|
||||
|
||||
- `app-store.ts`: Global app state (projects, features, settings, boards, themes)
|
||||
- `setup-store.ts`: First-time setup wizard flow
|
||||
- `ideation-store.ts`: Ideation feature state
|
||||
- `test-runners-store.ts`: Test runner configurations
|
||||
- Settings now persist via API (`/api/settings`) rather than localStorage (see use-settings-sync.ts)
|
||||
|
||||
**Backend State (Services):**
|
||||
|
||||
- SettingsService: Global and project-specific settings (in-memory with file persistence)
|
||||
- AgentService: Active agent sessions and conversation history
|
||||
- FeatureLoader: Feature data model operations
|
||||
- DevServerService: Development server logs
|
||||
- EventHistoryService: Persists event logs for replay
|
||||
|
||||
**Real-Time Updates (WebSocket):**
|
||||
|
||||
- Server EventEmitter emits TypedEvent (type + payload)
|
||||
- WebSocket handler subscribes to events and broadcasts to all clients
|
||||
- Frontend listens on multiple WebSocket subscriptions and updates stores
|
||||
|
||||
## Key Abstractions
|
||||
|
||||
**Feature:**
|
||||
|
||||
- Purpose: Represents a development task/story with rich metadata
|
||||
- Location: @automaker/types → `libs/types/src/feature.ts`
|
||||
- Fields: id, title, description, status, images, tasks, priority, etc.
|
||||
- Stored: `.automaker/features/{featureId}/feature.json`
|
||||
|
||||
**Provider:**
|
||||
|
||||
- Purpose: Abstracts different AI model implementations
|
||||
- Location: `apps/server/src/providers/{provider}-provider.ts`
|
||||
- Interface: Common execute() method with consistent message format
|
||||
- Implementations: Claude, Cursor, Codex, Gemini, OpenCode, Copilot
|
||||
- Factory: ProviderFactory picks correct provider based on model ID
|
||||
|
||||
**Event:**
|
||||
|
||||
- Purpose: Real-time updates streamed to frontend
|
||||
- Location: @automaker/types → `libs/types/src/event.ts`
|
||||
- Format: { type: EventType, payload: unknown }
|
||||
- Examples: agent-started, agent-step, agent-complete, feature-updated, etc.
|
||||
|
||||
**AgentSession:**
|
||||
|
||||
- Purpose: Represents a conversation between user and AI agent
|
||||
- Location: @automaker/types → `libs/types/src/session.ts`
|
||||
- Contains: Messages (user + assistant), metadata, creation timestamp
|
||||
- Stored: `{DATA_DIR}/agent-sessions/{sessionId}.json`
|
||||
|
||||
**Settings:**
|
||||
|
||||
- Purpose: Configuration for global and per-project behavior
|
||||
- Location: @automaker/types → `libs/types/src/settings.ts`
|
||||
- Stored: Global in `{DATA_DIR}/settings.json`, per-project in `.automaker/settings.json`
|
||||
- Service: SettingsService in `apps/server/src/services/settings-service.ts`
|
||||
|
||||
## Entry Points
|
||||
|
||||
**Server:**
|
||||
|
||||
- Location: `apps/server/src/index.ts`
|
||||
- Triggers: `npm run dev:server` or Docker startup
|
||||
- Responsibilities:
|
||||
- Initialize Express app with middleware
|
||||
- Create shared EventEmitter for WebSocket streaming
|
||||
- Bootstrap services (SettingsService, AgentService, FeatureLoader, etc.)
|
||||
- Mount API routes at `/api/*`
|
||||
- Create WebSocket servers for agent streaming and terminal sessions
|
||||
- Load and apply user settings (log level, request logging, etc.)
|
||||
|
||||
**UI (Web):**
|
||||
|
||||
- Location: `apps/ui/src/main.ts` (Vite entry), `apps/ui/src/app.tsx` (React component)
|
||||
- Triggers: `npm run dev:web` or `npm run build`
|
||||
- Responsibilities:
|
||||
- Initialize Zustand stores from API settings
|
||||
- Setup React Router with TanStack Router
|
||||
- Render root layout with sidebar and main content area
|
||||
- Handle authentication via verifySession()
|
||||
|
||||
**UI (Electron):**
|
||||
|
||||
- Location: `apps/ui/src/main.ts` (Vite entry), `apps/ui/electron/main-process.ts` (Electron main process)
|
||||
- Triggers: `npm run dev:electron`
|
||||
- Responsibilities:
|
||||
- Launch local server via node-pty
|
||||
- Create native Electron window
|
||||
- Bridge IPC between renderer and main process
|
||||
- Provide file system access via preload.ts APIs
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Strategy:** Layered error classification and user-friendly messaging
|
||||
|
||||
**Patterns:**
|
||||
|
||||
**Backend Error Handling:**
|
||||
|
||||
- Errors classified via `classifyError()` from @automaker/utils
|
||||
- Classification: ParseError, NetworkError, AuthenticationError, RateLimitError, etc.
|
||||
- Response format: `{ success: false, error: { type, message, code }, details? }`
|
||||
- Example: `apps/server/src/lib/error-handler.ts`
|
||||
|
||||
**Frontend Error Handling:**
|
||||
|
||||
- HTTP errors caught by api-fetch.ts with retry logic
|
||||
- WebSocket disconnects trigger reconnection with exponential backoff
|
||||
- Errors shown in toast notifications via `sonner` library
|
||||
- Validation errors caught and displayed inline in forms
|
||||
|
||||
**Agent Execution Errors:**
|
||||
|
||||
- AgentService wraps provider calls in try-catch
|
||||
- Aborts handled specially via `isAbortError()` check
|
||||
- Rate limit errors trigger cooldown before retry
|
||||
- Model-specific errors mapped to user guidance
|
||||
|
||||
## Cross-Cutting Concerns
|
||||
|
||||
**Logging:**
|
||||
|
||||
- Framework: @automaker/utils createLogger()
|
||||
- Pattern: `const logger = createLogger('ModuleName')`
|
||||
- Levels: ERROR, WARN, INFO, DEBUG (configurable via settings)
|
||||
- Output: stdout (dev), files (production)
|
||||
|
||||
**Validation:**
|
||||
|
||||
- File path validation: @automaker/platform initAllowedPaths() enforces restrictions
|
||||
- Model ID validation: @automaker/model-resolver resolveModelString()
|
||||
- JSON schema validation: Manual checks in route handlers (no JSON schema lib)
|
||||
- Authentication: Session token validation via validateWsConnectionToken()
|
||||
|
||||
**Authentication:**
|
||||
|
||||
- Frontend: Session token stored in httpOnly cookie
|
||||
- Backend: authMiddleware checks token on protected routes
|
||||
- WebSocket: validateWsConnectionToken() for upgrade requests
|
||||
- Providers: API keys stored encrypted in `{DATA_DIR}/credentials.json`
|
||||
|
||||
**Internationalization:**
|
||||
|
||||
- Not detected - strings are English-only
|
||||
|
||||
**Performance:**
|
||||
|
||||
- Code splitting: File-based routing via TanStack Router
|
||||
- Lazy loading: React.lazy() in route components
|
||||
- Caching: React Query for HTTP requests (query-keys.ts defines cache strategy)
|
||||
- Image optimization: Automatic base64 encoding for agent context
|
||||
- State hydration: Settings loaded once at startup, synced via API
|
||||
|
||||
---
|
||||
|
||||
_Architecture analysis: 2026-01-27_
|
||||
245
.planning/codebase/CONCERNS.md
Normal file
245
.planning/codebase/CONCERNS.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# Codebase Concerns
|
||||
|
||||
**Analysis Date:** 2026-01-27
|
||||
|
||||
## Tech Debt
|
||||
|
||||
**Loose Type Safety in Error Handling:**
|
||||
|
||||
- Issue: Multiple uses of `as any` type assertions bypass TypeScript safety, particularly in error context handling and provider responses
|
||||
- Files: `apps/server/src/providers/claude-provider.ts` (lines 318-322), `apps/server/src/lib/error-handler.ts`, `apps/server/src/routes/settings/routes/update-global.ts`
|
||||
- Impact: Errors could have unchecked properties; refactoring becomes risky without compiler assistance
|
||||
- Fix approach: Replace `as any` with proper type guards and discriminated unions; create helper functions for safe property access
|
||||
|
||||
**Missing Test Coverage for Critical Services:**
|
||||
|
||||
- Issue: Several core services explicitly excluded from test coverage thresholds due to integration complexity
|
||||
- Files: `apps/server/vitest.config.ts` (line 22), explicitly excluded: `claude-usage-service.ts`, `mcp-test-service.ts`, `cli-provider.ts`, `cursor-provider.ts`
|
||||
- Impact: Usage tracking, MCP integration, and CLI detection could break undetected; regression detection is limited
|
||||
- Fix approach: Create integration test fixtures for CLI providers; mock MCP SDK for mcp-test-service tests; add usage tracking unit tests with mocked API calls
|
||||
|
||||
**Unused/Stub TODO Item Processing:**
|
||||
|
||||
- Issue: TodoWrite tool implementation exists but is partially integrated; tool name constants scattered across codex provider
|
||||
- Files: `apps/server/src/providers/codex-tool-mapping.ts`, `apps/server/src/providers/codex-provider.ts`
|
||||
- Impact: Todo list updates may not synchronize properly with all providers; unclear which providers support TodoWrite
|
||||
- Fix approach: Consolidate tool name constants; add provider capability flags for todo support
|
||||
|
||||
**Electron Electron.ts Size and Complexity:**
|
||||
|
||||
- Issue: Single 3741-line file handles all Electron IPC, native bindings, and communication
|
||||
- Files: `apps/ui/src/lib/electron.ts`
|
||||
- Impact: Difficult to test; hard to isolate bugs; changes require full testing of all features; potential memory overhead from monolithic file
|
||||
- Fix approach: Split by responsibility (IPC, window management, file operations, debug tools); create separate bridge layers
|
||||
|
||||
## Known Bugs
|
||||
|
||||
**API Key Management Incomplete for Gemini:**
|
||||
|
||||
- Symptoms: Gemini API key verification endpoint not implemented despite other providers having verification
|
||||
- Files: `apps/ui/src/components/views/settings-view/api-keys/hooks/use-api-key-management.ts` (line 122)
|
||||
- Trigger: User tries to verify Gemini API key in settings
|
||||
- Workaround: Key verification skipped for Gemini; settings page still accepts and stores key
|
||||
|
||||
**Orphaned Features Detection Vulnerable to False Negatives:**
|
||||
|
||||
- Symptoms: Features marked as orphaned when branch matching logic doesn't account for all scenarios
|
||||
- Files: `apps/server/src/services/auto-mode-service.ts` (lines 5714-5773)
|
||||
- Trigger: Features that were manually switched branches or rebased
|
||||
- Workaround: Manual cleanup via feature deletion; branch comparison is basic name matching only
|
||||
|
||||
**Terminal Themes Incomplete:**
|
||||
|
||||
- Symptoms: Light theme themes (solarizedlight, github) map to same generic lightTheme; no dedicated implementations
|
||||
- Files: `apps/ui/src/config/terminal-themes.ts` (lines 593-594)
|
||||
- Trigger: User selects solarizedlight or github terminal theme
|
||||
- Workaround: Uses generic light theme instead of specific scheme; visual appearance doesn't match expectation
|
||||
|
||||
## Security Considerations
|
||||
|
||||
**Process Environment Variable Exposure:**
|
||||
|
||||
- Risk: Child processes inherit all parent `process.env` including sensitive credentials (API keys, tokens)
|
||||
- Files: `apps/server/src/providers/cursor-provider.ts` (line 993), `apps/server/src/providers/codex-provider.ts` (line 1099)
|
||||
- Current mitigation: Dotenv provides isolation at app startup; selective env passing to some providers
|
||||
- Recommendations: Use explicit allowlists for env vars passed to child processes (only pass REQUIRED_KEYS); audit all spawn calls for env handling; document which providers need which credentials
|
||||
|
||||
**Unvalidated Provider Tool Input:**
|
||||
|
||||
- Risk: Tool input from CLI providers (Cursor, Copilot, Codex) is partially validated through Record<string, unknown> patterns; execution context could be escaped
|
||||
- Files: `apps/server/src/providers/codex-provider.ts` (lines 506-543), `apps/server/src/providers/tool-normalization.ts`
|
||||
- Current mitigation: Status enums validated; tool names checked against allow-lists in some providers
|
||||
- Recommendations: Implement comprehensive schema validation for all tool inputs before execution; use zod or similar for runtime validation; add security tests for injection patterns
|
||||
|
||||
**API Key Storage in Settings Files:**
|
||||
|
||||
- Risk: API keys stored in plaintext in `~/.automaker/settings.json` and `data/settings.json`; file permissions may not be restricted
|
||||
- Files: `apps/server/src/services/settings-service.ts`, uses `atomicWriteJson` without file permission enforcement
|
||||
- Current mitigation: Limited by file system permissions; Electron mode has single-user access
|
||||
- Recommendations: Encrypt sensitive settings fields (apiKeys, tokens); use OS credential stores (Keychain/Credential Manager) for production; add file permission checks on startup
|
||||
|
||||
## Performance Bottlenecks
|
||||
|
||||
**Synchronous Feature Loading at Startup:**
|
||||
|
||||
- Problem: All features loaded synchronously at project load; blocks UI with 1000+ features
|
||||
- Files: `apps/server/src/services/feature-loader.ts` (line 230 Promise.all, but synchronous enumeration)
|
||||
- Cause: Feature directory walk and JSON parsing is not paginated or lazy-loaded
|
||||
- Improvement path: Implement lazy loading with pagination (load first 50, fetch more on scroll); add caching layer with TTL; move to background indexing; add feature count limits with warnings
|
||||
|
||||
**Auto-Mode Concurrency at Max Can Exceed Rate Limits:**
|
||||
|
||||
- Problem: maxConcurrency = 10 can quickly exhaust Claude API rate limits if all features execute simultaneously
|
||||
- Files: `apps/server/src/services/auto-mode-service.ts` (line 2931 Promise.all for concurrent agents)
|
||||
- Cause: No adaptive backoff; no API usage tracking before queuing; hint mentions reducing concurrency but doesn't enforce it
|
||||
- Improvement path: Integrate with claude-usage-service to check remaining quota before starting features; implement exponential backoff on 429 errors; add per-model rate limit tracking
|
||||
|
||||
**Terminal Session Memory Leak Risk:**
|
||||
|
||||
- Problem: Terminal sessions accumulate in memory; expired sessions not cleaned up reliably
|
||||
- Files: `apps/server/src/routes/terminal/common.ts` (line 66 cleanup runs every 5 minutes, but only for tokens)
|
||||
- Cause: Cleanup interval is arbitrary; session map not bounded; no session lifespan limit
|
||||
- Improvement path: Implement LRU eviction with max session count; reduce cleanup interval to 1 minute; add memory usage monitoring; auto-close idle sessions after 30 minutes
|
||||
|
||||
**Large File Content Loading Without Limits:**
|
||||
|
||||
- Problem: File content loaded entirely into memory; `describe-file.ts` truncates at 50KB but loads all content first
|
||||
- Files: `apps/server/src/routes/context/routes/describe-file.ts` (line 128)
|
||||
- Cause: Synchronous file read; no streaming; no check before reading large files
|
||||
- Improvement path: Check file size before reading; stream large files; add file size warnings; implement chunked processing for analysis
|
||||
|
||||
## Fragile Areas
|
||||
|
||||
**Provider Factory Model Resolution:**
|
||||
|
||||
- Files: `apps/server/src/providers/provider-factory.ts`, `apps/server/src/providers/simple-query-service.ts`
|
||||
- Why fragile: Each provider interprets model strings differently; no central registry; model aliases resolved at multiple layers (model-resolver, provider-specific maps, CLI validation)
|
||||
- Safe modification: Add integration tests for each model alias per provider; create model capability matrix; centralize model validation before dispatch
|
||||
- Test coverage: No dedicated tests; relies on E2E; no isolated unit tests for model resolution
|
||||
|
||||
**WebSocket Session Authentication:**
|
||||
|
||||
- Files: `apps/server/src/lib/auth.ts` (line 40 setInterval), `apps/server/src/index.ts` (token validation per message)
|
||||
- Why fragile: Session tokens generated and validated at multiple points; no single source of truth; expiration is not atomic
|
||||
- Safe modification: Add tests for token expiration edge cases; ensure cleanup removes all references; log all auth failures
|
||||
- Test coverage: Auth middleware tested, but not session lifecycle
|
||||
|
||||
**Auto-Mode Feature State Machine:**
|
||||
|
||||
- Files: `apps/server/src/services/auto-mode-service.ts` (lines 465-600)
|
||||
- Why fragile: Multiple states (running, queued, completed, error) managed across different methods; no explicit state transition validation; error recovery is defensive (catches all, logs, continues)
|
||||
- Safe modification: Create explicit state enum with valid transitions; add invariant checks; unit test state transitions with all error cases
|
||||
- Test coverage: Gaps in error recovery paths; no tests for concurrent state changes
|
||||
|
||||
## Scaling Limits
|
||||
|
||||
**Feature Count Scalability:**
|
||||
|
||||
- Current capacity: ~1000 features tested; UI performance degrades with pagination required
|
||||
- Limit: 10K+ features cause >5s load times; memory usage ~100MB for metadata alone
|
||||
- Scaling path: Implement feature database instead of file-per-feature; add ElasticSearch indexing for search; paginate API responses (50 per page); add feature archiving
|
||||
|
||||
**Concurrent Auto-Mode Executions:**
|
||||
|
||||
- Current capacity: maxConcurrency = 10 features; limited by Claude API rate limits
|
||||
- Limit: Rate limit hits at ~4-5 simultaneous features with extended context (100K+ tokens)
|
||||
- Scaling path: Implement token usage budgeting before feature start; queue features with estimated token cost; add provider-specific rate limit handling
|
||||
|
||||
**Terminal Session Count:**
|
||||
|
||||
- Current capacity: ~100 active terminal sessions per server
|
||||
- Limit: Memory grows unbounded; no session count limit enforced
|
||||
- Scaling path: Add max session count with least-recently-used eviction; implement session federation for distributed setup
|
||||
|
||||
**Worktree Disk Usage:**
|
||||
|
||||
- Current capacity: 10K worktrees (~20GB with typical repos)
|
||||
- Limit: `.worktrees` directory grows without cleanup; old worktrees accumulate
|
||||
- Scaling path: Add worktree TTL (delete if not used for 30 days); implement cleanup job; add quota warnings at 50/80% disk
|
||||
|
||||
## Dependencies at Risk
|
||||
|
||||
**node-pty Beta Version:**
|
||||
|
||||
- Risk: `node-pty@1.1.0-beta41` used for terminal emulation; beta status indicates possible instability
|
||||
- Impact: Terminal features could break on minor platform changes; no guarantees on bug fixes
|
||||
- Migration plan: Monitor releases for stable version; pin to specific commit if needed; test extensively on target platforms (macOS, Linux, Windows)
|
||||
|
||||
**@anthropic-ai/claude-agent-sdk 0.1.x:**
|
||||
|
||||
- Risk: Pre-1.0 version; SDK API may change in future releases; limited version stability guarantees
|
||||
- Impact: Breaking changes could require significant refactoring; feature additions in SDK may not align with Automaker roadmap
|
||||
- Migration plan: Pin to specific 0.1.x version; review SDK changelogs before upgrades; maintain SDK compatibility tests; consider fallback implementation for critical paths
|
||||
|
||||
**@openai/codex-sdk 0.77.x:**
|
||||
|
||||
- Risk: Codex model deprecated by OpenAI; SDK may be archived or unsupported
|
||||
- Impact: Codex provider could become non-functional; error messages may not be actionable
|
||||
- Migration plan: Monitor OpenAI roadmap for migration path; implement fallback to Claude for Codex requests; add deprecation warning in UI
|
||||
|
||||
**Express 5.2.x RC Stage:**
|
||||
|
||||
- Risk: Express 5 is still in release candidate phase (as of Node 22); full stability not guaranteed
|
||||
- Impact: Minor version updates could include breaking changes; middleware compatibility issues possible
|
||||
- Migration plan: Maintain compatibility layer for Express 5 API; test with latest major before release; document any version-specific workarounds
|
||||
|
||||
## Missing Critical Features
|
||||
|
||||
**Persistent Session Storage:**
|
||||
|
||||
- Problem: Agent conversation sessions stored only in-memory; restart loses all chat history
|
||||
- Blocks: Long-running analysis across server restarts; session recovery not possible
|
||||
- Impact: Users must re-run entire analysis if server restarts; lost productivity
|
||||
|
||||
**Rate Limit Awareness:**
|
||||
|
||||
- Problem: No tracking of API usage relative to rate limits before executing features
|
||||
- Blocks: Predictable concurrent feature execution; users frequently hit rate limits unexpectedly
|
||||
- Impact: Feature execution fails with cryptic rate limit errors; poor user experience
|
||||
|
||||
**Feature Dependency Visualization:**
|
||||
|
||||
- Problem: Dependency-resolver package exists but no UI to visualize or manage dependencies
|
||||
- Blocks: Users cannot plan feature order; complex dependencies not visible
|
||||
- Impact: Features implemented in wrong order; blocking dependencies missed
|
||||
|
||||
## Test Coverage Gaps
|
||||
|
||||
**CLI Provider Integration:**
|
||||
|
||||
- What's not tested: Actual CLI execution paths; environment setup; error recovery from CLI crashes
|
||||
- Files: `apps/server/src/providers/cli-provider.ts`, `apps/server/src/lib/cli-detection.ts`
|
||||
- Risk: Changes to CLI handling could break silently; detection logic not validated on target platforms
|
||||
- Priority: High - affects all CLI-based providers (Cursor, Copilot, Codex)
|
||||
|
||||
**Cursor Provider Platform-Specific Paths:**
|
||||
|
||||
- What's not tested: Windows/Linux Cursor installation detection; version directory parsing; APPDATA environment variable handling
|
||||
- Files: `apps/server/src/providers/cursor-provider.ts` (lines 267-498)
|
||||
- Risk: Platform-specific bugs not caught; Cursor detection fails on non-standard installations
|
||||
- Priority: High - Cursor is primary provider; platform differences critical
|
||||
|
||||
**Event Hook System State Changes:**
|
||||
|
||||
- What's not tested: Concurrent hook execution; cleanup on server shutdown; webhook delivery retries
|
||||
- Files: `apps/server/src/services/event-hook-service.ts` (line 248 Promise.allSettled)
|
||||
- Risk: Hooks may not execute in expected order; memory not cleaned up; webhooks lost on failure
|
||||
- Priority: Medium - affects automation workflows
|
||||
|
||||
**Error Classification for New Providers:**
|
||||
|
||||
- What's not tested: Each provider's unique error patterns mapped to ErrorType enum; new provider errors not classified
|
||||
- Files: `apps/server/src/lib/error-handler.ts` (lines 58-80), each provider error mapping
|
||||
- Risk: User sees generic "unknown error" instead of actionable message; categorization regresses with new providers
|
||||
- Priority: Medium - impacts user experience
|
||||
|
||||
**Feature State Corruption Scenarios:**
|
||||
|
||||
- What's not tested: Concurrent feature updates; partial writes with power loss; JSON parsing recovery
|
||||
- Files: `apps/server/src/services/feature-loader.ts`, `@automaker/utils` (atomicWriteJson)
|
||||
- Risk: Feature data corrupted on concurrent access; recovery incomplete; no validation before use
|
||||
- Priority: High - data loss risk
|
||||
|
||||
---
|
||||
|
||||
_Concerns audit: 2026-01-27_
|
||||
255
.planning/codebase/CONVENTIONS.md
Normal file
255
.planning/codebase/CONVENTIONS.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Coding Conventions
|
||||
|
||||
**Analysis Date:** 2026-01-27
|
||||
|
||||
## Naming Patterns
|
||||
|
||||
**Files:**
|
||||
|
||||
- PascalCase for class/service files: `auto-mode-service.ts`, `feature-loader.ts`, `claude-provider.ts`
|
||||
- kebab-case for route/handler directories: `auto-mode/`, `features/`, `event-history/`
|
||||
- kebab-case for utility files: `secure-fs.ts`, `sdk-options.ts`, `settings-helpers.ts`
|
||||
- kebab-case for React components: `card.tsx`, `ansi-output.tsx`, `count-up-timer.tsx`
|
||||
- kebab-case for hooks: `use-board-background-settings.ts`, `use-responsive-kanban.ts`, `use-test-logs.ts`
|
||||
- kebab-case for store files: `app-store.ts`, `auth-store.ts`, `setup-store.ts`
|
||||
- Organized by functionality: `routes/features/routes/list.ts`, `routes/features/routes/get.ts`
|
||||
|
||||
**Functions:**
|
||||
|
||||
- camelCase for all function names: `createEventEmitter()`, `getAutomakerDir()`, `executeQuery()`
|
||||
- Verb-first for action functions: `buildPrompt()`, `classifyError()`, `loadContextFiles()`, `atomicWriteJson()`
|
||||
- Prefix with `use` for React hooks: `useBoardBackgroundSettings()`, `useAppStore()`, `useUpdateProjectSettings()`
|
||||
- Private methods prefixed with underscore: `_deleteOrphanedImages()`, `_migrateImages()`
|
||||
|
||||
**Variables:**
|
||||
|
||||
- camelCase for constants and variables: `featureId`, `projectPath`, `modelId`, `tempDir`
|
||||
- UPPER_SNAKE_CASE for global constants/enums: `DEFAULT_MAX_CONCURRENCY`, `DEFAULT_PHASE_MODELS`
|
||||
- Meaningful naming over abbreviations: `featureDirectory` not `fd`, `featureImages` not `img`
|
||||
- Prefixes for computed values: `is*` for booleans: `isClaudeModel`, `isContainerized`, `isAutoLoginEnabled`
|
||||
|
||||
**Types:**
|
||||
|
||||
- PascalCase for interfaces and types: `Feature`, `ExecuteOptions`, `EventEmitter`, `ProviderConfig`
|
||||
- Type files suffixed with `.d.ts`: `paths.d.ts`, `types.d.ts`
|
||||
- Organized by domain: `src/store/types/`, `src/lib/`
|
||||
- Re-export pattern from main package indexes: `export type { Feature };`
|
||||
|
||||
## Code Style
|
||||
|
||||
**Formatting:**
|
||||
|
||||
- Tool: Prettier 3.7.4
|
||||
- Print width: 100 characters
|
||||
- Tab width: 2 spaces
|
||||
- Single quotes for strings
|
||||
- Semicolons required
|
||||
- Trailing commas: es5 (trailing in arrays/objects, not in params)
|
||||
- Arrow functions always include parentheses: `(x) => x * 2`
|
||||
- Line endings: LF (Unix)
|
||||
- Bracket spacing: `{ key: value }`
|
||||
|
||||
**Linting:**
|
||||
|
||||
- Tool: ESLint (flat config in `apps/ui/eslint.config.mjs`)
|
||||
- TypeScript ESLint plugin for `.ts`/`.tsx` files
|
||||
- Recommended configs: `@eslint/js`, `@typescript-eslint/recommended`
|
||||
- Unused variables warning with exception for parameters starting with `_`
|
||||
- Type assertions are allowed with description when using `@ts-ignore`
|
||||
- `@typescript-eslint/no-explicit-any` is warn-level (allow with caution)
|
||||
|
||||
## Import Organization
|
||||
|
||||
**Order:**
|
||||
|
||||
1. Node.js standard library: `import fs from 'fs/promises'`, `import path from 'path'`
|
||||
2. Third-party packages: `import { describe, it } from 'vitest'`, `import { Router } from 'express'`
|
||||
3. Shared packages (monorepo): `import type { Feature } from '@automaker/types'`, `import { createLogger } from '@automaker/utils'`
|
||||
4. Local relative imports: `import { FeatureLoader } from './feature-loader.js'`, `import * as secureFs from '../lib/secure-fs.js'`
|
||||
5. Type imports: separated with `import type { ... } from`
|
||||
|
||||
**Path Aliases:**
|
||||
|
||||
- `@/` - resolves to `./src` in both UI (`apps/ui/`) and server (`apps/server/`)
|
||||
- Shared packages prefixed with `@automaker/`:
|
||||
- `@automaker/types` - core TypeScript definitions
|
||||
- `@automaker/utils` - logging, errors, utilities
|
||||
- `@automaker/prompts` - AI prompt templates
|
||||
- `@automaker/platform` - path management, security, processes
|
||||
- `@automaker/model-resolver` - model alias resolution
|
||||
- `@automaker/dependency-resolver` - feature dependency ordering
|
||||
- `@automaker/git-utils` - git operations
|
||||
- Extensions: `.js` extension used in imports for ESM imports
|
||||
|
||||
**Import Rules:**
|
||||
|
||||
- Always import from shared packages, never from old paths
|
||||
- No circular dependencies between layers
|
||||
- Services import from providers and utilities
|
||||
- Routes import from services
|
||||
- Shared packages have strict dependency hierarchy (types → utils → platform → git-utils → server/ui)
|
||||
|
||||
## Error Handling
|
||||
|
||||
**Patterns:**
|
||||
|
||||
- Use `try-catch` blocks for async operations: wraps feature execution, file operations, git commands
|
||||
- Throw `new Error(message)` with descriptive messages: `throw new Error('already running')`, `throw new Error('Feature ${featureId} not found')`
|
||||
- Classify errors with `classifyError()` from `@automaker/utils` for categorization
|
||||
- Log errors with context using `createLogger()`: includes error classification
|
||||
- Return error info objects: `{ valid: false, errors: [...], warnings: [...] }`
|
||||
- Validation returns structured result: `{ valid, errors, warnings }` from provider `validateConfig()`
|
||||
|
||||
**Error Types:**
|
||||
|
||||
- Authentication errors: distinguish from validation/runtime errors
|
||||
- Path validation errors: caught by middleware in Express routes
|
||||
- File system errors: logged and recovery attempted with backups
|
||||
- SDK/API errors: classified and wrapped with context
|
||||
- Abort/cancellation errors: handled without stack traces (graceful shutdown)
|
||||
|
||||
**Error Messages:**
|
||||
|
||||
- Descriptive and actionable: not vague error codes
|
||||
- Include context when helpful: file paths, feature IDs, model names
|
||||
- User-friendly messages via `getUserFriendlyErrorMessage()` for client display
|
||||
|
||||
## Logging
|
||||
|
||||
**Framework:**
|
||||
|
||||
- Built-in `createLogger()` from `@automaker/utils`
|
||||
- Each module creates logger: `const logger = createLogger('ModuleName')`
|
||||
- Logger functions: `info()`, `warn()`, `error()`, `debug()`
|
||||
|
||||
**Patterns:**
|
||||
|
||||
- Log operation start and completion for significant operations
|
||||
- Log warnings for non-critical issues: file deletion failures, missing optional configs
|
||||
- Log errors with full error object: `logger.error('operation failed', error)`
|
||||
- Use module name as logger context: `createLogger('AutoMode')`, `createLogger('HttpClient')`
|
||||
- Avoid logging sensitive data (API keys, passwords)
|
||||
- No console.log in production code - use logger
|
||||
|
||||
**What to Log:**
|
||||
|
||||
- Feature execution start/completion
|
||||
- Error classification and recovery attempts
|
||||
- File operations (create, delete, migrate)
|
||||
- API calls and responses (in debug mode)
|
||||
- Async operation start/end
|
||||
- Warnings for deprecated patterns
|
||||
|
||||
## Comments
|
||||
|
||||
**When to Comment:**
|
||||
|
||||
- Complex algorithms or business logic: explain the "why" not the "what"
|
||||
- Integration points: explain how modules communicate
|
||||
- Workarounds: explain the constraint that made the workaround necessary
|
||||
- Non-obvious performance implications
|
||||
- Edge cases and their handling
|
||||
|
||||
**JSDoc/TSDoc:**
|
||||
|
||||
- Used for public functions and classes
|
||||
- Document parameters with `@param`
|
||||
- Document return types with `@returns`
|
||||
- Document exceptions with `@throws`
|
||||
- Used for service classes: `/**\n * Module description\n * Manages: ...\n */`
|
||||
- Not required for simple getters/setters
|
||||
|
||||
**Example JSDoc Pattern:**
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Delete images that were removed from a feature
|
||||
*/
|
||||
private async deleteOrphanedImages(
|
||||
projectPath: string,
|
||||
oldPaths: Array<string>,
|
||||
newPaths: Array<string>
|
||||
): Promise<void> {
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
## Function Design
|
||||
|
||||
**Size:**
|
||||
|
||||
- Keep functions under 100 lines when possible
|
||||
- Large services split into multiple related methods
|
||||
- Private helper methods extracted for complex logic
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- Use destructuring for object parameters with multiple properties
|
||||
- Document parameter types with TypeScript types
|
||||
- Optional parameters marked with `?`
|
||||
- Use `Record<string, unknown>` for flexible object parameters
|
||||
|
||||
**Return Values:**
|
||||
|
||||
- Explicit return types required for all public functions
|
||||
- Return structured objects for multiple values
|
||||
- Use `Promise<T>` for async functions
|
||||
- Async generators use `AsyncGenerator<T>` for streaming responses
|
||||
- Never implicitly return `undefined` (explicit return or throw)
|
||||
|
||||
## Module Design
|
||||
|
||||
**Exports:**
|
||||
|
||||
- Default export for class instantiation: `export default class FeatureLoader {}`
|
||||
- Named exports for functions: `export function createEventEmitter() {}`
|
||||
- Type exports separated: `export type { Feature };`
|
||||
- Barrel files (index.ts) re-export from module
|
||||
|
||||
**Barrel Files:**
|
||||
|
||||
- Used in routes: `routes/features/index.ts` creates router and exports
|
||||
- Used in stores: `store/index.ts` exports all store hooks
|
||||
- Pattern: group related exports for easier importing
|
||||
|
||||
**Service Classes:**
|
||||
|
||||
- Instantiated once and dependency injected
|
||||
- Public methods for API surface
|
||||
- Private methods prefixed with `_`
|
||||
- No static methods - prefer instances or functions
|
||||
- Constructor takes dependencies: `constructor(config?: ProviderConfig)`
|
||||
|
||||
**Provider Pattern:**
|
||||
|
||||
- Abstract base class: `BaseProvider` with abstract methods
|
||||
- Concrete implementations: `ClaudeProvider`, `CodexProvider`, `CursorProvider`
|
||||
- Common interface: `executeQuery()`, `detectInstallation()`, `validateConfig()`
|
||||
- Factory for instantiation: `ProviderFactory.create()`
|
||||
|
||||
## TypeScript Specific
|
||||
|
||||
**Strict Mode:** Always enabled globally
|
||||
|
||||
- `strict: true` in all tsconfigs
|
||||
- No implicit `any` - declare types explicitly
|
||||
- No optional chaining on base types without narrowing
|
||||
|
||||
**Type Definitions:**
|
||||
|
||||
- Interface for shapes: `interface Feature { ... }`
|
||||
- Type for unions/aliases: `type ModelAlias = 'haiku' | 'sonnet' | 'opus'`
|
||||
- Type guards for narrowing: `if (typeof x === 'string') { ... }`
|
||||
- Generic types for reusable patterns: `EventCallback<T>`
|
||||
|
||||
**React Specific (UI):**
|
||||
|
||||
- Functional components only
|
||||
- React 19 with hooks
|
||||
- Type props interface: `interface CardProps extends React.ComponentProps<'div'> { ... }`
|
||||
- Zustand stores for state management
|
||||
- Custom hooks for shared logic
|
||||
|
||||
---
|
||||
|
||||
_Convention analysis: 2026-01-27_
|
||||
232
.planning/codebase/INTEGRATIONS.md
Normal file
232
.planning/codebase/INTEGRATIONS.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# External Integrations
|
||||
|
||||
**Analysis Date:** 2026-01-27
|
||||
|
||||
## APIs & External Services
|
||||
|
||||
**AI/LLM Providers:**
|
||||
|
||||
- Claude (Anthropic)
|
||||
- SDK: `@anthropic-ai/claude-agent-sdk` (0.1.76)
|
||||
- Auth: `ANTHROPIC_API_KEY` environment variable or stored credentials
|
||||
- Features: Extended thinking, vision/images, tools, streaming
|
||||
- Implementation: `apps/server/src/providers/claude-provider.ts`
|
||||
- Models: Opus 4.5, Sonnet 4, Haiku 4.5, and legacy models
|
||||
- Custom endpoints: `ANTHROPIC_BASE_URL` (optional)
|
||||
|
||||
- GitHub Copilot
|
||||
- SDK: `@github/copilot-sdk` (0.1.16)
|
||||
- Auth: GitHub OAuth (via `gh` CLI) or `GITHUB_TOKEN` environment variable
|
||||
- Features: Tools, streaming, runtime model discovery
|
||||
- Implementation: `apps/server/src/providers/copilot-provider.ts`
|
||||
- CLI detection: Searches for Copilot CLI binary
|
||||
- Models: Dynamic discovery via `copilot models list`
|
||||
|
||||
- OpenAI Codex/GPT-4
|
||||
- SDK: `@openai/codex-sdk` (0.77.0)
|
||||
- Auth: `OPENAI_API_KEY` environment variable or stored credentials
|
||||
- Features: Extended thinking, tools, sandbox execution
|
||||
- Implementation: `apps/server/src/providers/codex-provider.ts`
|
||||
- Execution modes: CLI (with sandbox) or SDK (direct API)
|
||||
- Models: Dynamic discovery via Codex CLI or SDK
|
||||
|
||||
- Google Gemini
|
||||
- Implementation: `apps/server/src/providers/gemini-provider.ts`
|
||||
- Features: Vision support, tools, streaming
|
||||
|
||||
- OpenCode (AWS/Azure/other)
|
||||
- Implementation: `apps/server/src/providers/opencode-provider.ts`
|
||||
- Supports: Amazon Bedrock, Azure models, local models
|
||||
- Features: Flexible provider architecture
|
||||
|
||||
- Cursor Editor
|
||||
- Implementation: `apps/server/src/providers/cursor-provider.ts`
|
||||
- Features: Integration with Cursor IDE
|
||||
|
||||
**Model Context Protocol (MCP):**
|
||||
|
||||
- SDK: `@modelcontextprotocol/sdk` (1.25.2)
|
||||
- Purpose: Connect AI agents to external tools and data sources
|
||||
- Implementation: `apps/server/src/services/mcp-test-service.ts`, `apps/server/src/routes/mcp/`
|
||||
- Configuration: Per-project in `.automaker/` directory
|
||||
|
||||
## Data Storage
|
||||
|
||||
**Databases:**
|
||||
|
||||
- None - This codebase does NOT use traditional databases (SQL/NoSQL)
|
||||
- All data stored as files in local filesystem
|
||||
|
||||
**File Storage:**
|
||||
|
||||
- Local filesystem only
|
||||
- Locations:
|
||||
- `.automaker/` - Project-specific data (features, context, settings)
|
||||
- `./data/` or `DATA_DIR` env var - Global data (settings, credentials, sessions)
|
||||
- Secure file operations: `@automaker/platform` exports `secureFs` for restricted file access
|
||||
|
||||
**Caching:**
|
||||
|
||||
- In-memory caches for:
|
||||
- Model lists (Copilot, Codex runtime discovery)
|
||||
- Feature metadata
|
||||
- Project specifications
|
||||
- No distributed/persistent caching system
|
||||
|
||||
## Authentication & Identity
|
||||
|
||||
**Auth Provider:**
|
||||
|
||||
- Custom implementation (no third-party provider)
|
||||
- Authentication methods:
|
||||
1. Claude Max Plan (OAuth via Anthropic CLI)
|
||||
2. API Key mode (ANTHROPIC_API_KEY)
|
||||
3. Custom provider profiles with API keys
|
||||
4. Token-based session authentication for WebSocket
|
||||
|
||||
**Implementation:**
|
||||
|
||||
- `apps/server/src/lib/auth.ts` - Auth middleware
|
||||
- `apps/server/src/routes/auth/` - Auth routes
|
||||
- Session tokens for WebSocket connections
|
||||
- Credential storage in `./data/credentials.json` (encrypted/protected)
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
**Error Tracking:**
|
||||
|
||||
- None - No automatic error reporting service integrated
|
||||
- Custom error classification: `@automaker/utils` exports `classifyError()`
|
||||
- User-friendly error messages: `getUserFriendlyErrorMessage()`
|
||||
|
||||
**Logs:**
|
||||
|
||||
- Console logging with configurable levels
|
||||
- Logger: `@automaker/utils` exports `createLogger()`
|
||||
- Log levels: ERROR, WARN, INFO, DEBUG
|
||||
- Environment: `LOG_LEVEL` env var (optional)
|
||||
- Storage: Logs output to console/stdout (no persistent logging to files)
|
||||
|
||||
**Usage Tracking:**
|
||||
|
||||
- Claude API usage: `apps/server/src/services/claude-usage-service.ts`
|
||||
- Codex API usage: `apps/server/src/services/codex-usage-service.ts`
|
||||
- Tracks: Tokens, costs, rates
|
||||
|
||||
## CI/CD & Deployment
|
||||
|
||||
**Hosting:**
|
||||
|
||||
- Local development: Node.js server + Vite dev server
|
||||
- Desktop: Electron application (macOS, Windows, Linux)
|
||||
- Web: Express server deployed to any Node.js host
|
||||
|
||||
**CI Pipeline:**
|
||||
|
||||
- GitHub Actions likely (`.github/workflows/` present in repo)
|
||||
- Testing: Playwright E2E, Vitest unit tests
|
||||
- Linting: ESLint
|
||||
- Formatting: Prettier
|
||||
|
||||
**Build Process:**
|
||||
|
||||
- `npm run build:packages` - Build shared packages
|
||||
- `npm run build` - Build web UI
|
||||
- `npm run build:electron` - Build Electron apps (platform-specific)
|
||||
- Electron Builder handles code signing and distribution
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
**Required env vars:**
|
||||
|
||||
- `ANTHROPIC_API_KEY` - For Claude provider (or provide in settings)
|
||||
- `OPENAI_API_KEY` - For Codex provider (optional)
|
||||
- `GITHUB_TOKEN` - For GitHub operations (optional)
|
||||
|
||||
**Optional env vars:**
|
||||
|
||||
- `PORT` - Server port (default 3008)
|
||||
- `HOST` - Server bind address (default 0.0.0.0)
|
||||
- `HOSTNAME` - Public hostname (default localhost)
|
||||
- `DATA_DIR` - Data storage directory (default ./data)
|
||||
- `ANTHROPIC_BASE_URL` - Custom Claude endpoint
|
||||
- `ALLOWED_ROOT_DIRECTORY` - Restrict file operations to directory
|
||||
- `AUTOMAKER_MOCK_AGENT` - Enable mock agent for testing
|
||||
- `AUTOMAKER_AUTO_LOGIN` - Skip login prompt in dev
|
||||
|
||||
**Secrets location:**
|
||||
|
||||
- Runtime: Environment variables (`process.env`)
|
||||
- Stored: `./data/credentials.json` (file-based)
|
||||
- Retrieval: `apps/server/src/services/settings-service.ts`
|
||||
|
||||
## Webhooks & Callbacks
|
||||
|
||||
**Incoming:**
|
||||
|
||||
- WebSocket connections for real-time agent event streaming
|
||||
- GitHub webhook routes (optional): `apps/server/src/routes/github/`
|
||||
- Terminal WebSocket connections: `apps/server/src/routes/terminal/`
|
||||
|
||||
**Outgoing:**
|
||||
|
||||
- GitHub PRs: `apps/server/src/routes/worktree/routes/create-pr.ts`
|
||||
- Git operations: `@automaker/git-utils` handles commits, pushes
|
||||
- Terminal output streaming via WebSocket to clients
|
||||
- Event hooks: `apps/server/src/services/event-hook-service.ts`
|
||||
|
||||
## Credential Management
|
||||
|
||||
**API Keys Storage:**
|
||||
|
||||
- File: `./data/credentials.json`
|
||||
- Format: JSON with nested structure for different providers
|
||||
```json
|
||||
{
|
||||
"apiKeys": {
|
||||
"anthropic": "sk-...",
|
||||
"openai": "sk-...",
|
||||
"github": "ghp_..."
|
||||
}
|
||||
}
|
||||
```
|
||||
- Access: `SettingsService.getCredentials()` from `apps/server/src/services/settings-service.ts`
|
||||
- Security: File permissions should restrict to current user only
|
||||
|
||||
**Profile/Provider Configuration:**
|
||||
|
||||
- File: `./data/settings.json` (global) or `.automaker/settings.json` (per-project)
|
||||
- Stores: Alternative provider profiles, model mappings, sandbox settings
|
||||
- Types: `ClaudeApiProfile`, `ClaudeCompatibleProvider` from `@automaker/types`
|
||||
|
||||
## Third-Party Service Integration Points
|
||||
|
||||
**Git/GitHub:**
|
||||
|
||||
- `@automaker/git-utils` - Git operations (worktrees, commits, diffs)
|
||||
- Codex/Cursor providers can create GitHub PRs
|
||||
- GitHub CLI (`gh`) detection for Copilot authentication
|
||||
|
||||
**Terminal Access:**
|
||||
|
||||
- `node-pty` (1.1.0-beta41) - Pseudo-terminal interface
|
||||
- `TerminalService` manages terminal sessions
|
||||
- WebSocket streaming to frontend
|
||||
|
||||
**AI Models - Multi-Provider Abstraction:**
|
||||
|
||||
- `BaseProvider` interface: `apps/server/src/providers/base-provider.ts`
|
||||
- Factory pattern: `apps/server/src/providers/provider-factory.ts`
|
||||
- Allows swapping providers without changing agent logic
|
||||
- All providers implement: `executeQuery()`, `detectInstallation()`, `getAvailableModels()`
|
||||
|
||||
**Process Spawning:**
|
||||
|
||||
- `@automaker/platform` exports `spawnProcess()`, `spawnJSONLProcess()`
|
||||
- Codex CLI execution: JSONL output parsing
|
||||
- Copilot CLI execution: Subprocess management
|
||||
- Cursor IDE interaction: Process spawning for tool execution
|
||||
|
||||
---
|
||||
|
||||
_Integration audit: 2026-01-27_
|
||||
230
.planning/codebase/STACK.md
Normal file
230
.planning/codebase/STACK.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# Technology Stack
|
||||
|
||||
**Analysis Date:** 2026-01-27
|
||||
|
||||
## Languages
|
||||
|
||||
**Primary:**
|
||||
|
||||
- TypeScript 5.9.3 - Used across all packages, apps, and configuration
|
||||
- JavaScript (Node.js) - Runtime execution for scripts and tooling
|
||||
|
||||
**Secondary:**
|
||||
|
||||
- YAML 2.7.0 - Configuration files
|
||||
- CSS/Tailwind CSS 4.1.18 - Frontend styling
|
||||
|
||||
## Runtime
|
||||
|
||||
**Environment:**
|
||||
|
||||
- Node.js 22.x (>=22.0.0 <23.0.0) - Required version, specified in `.nvmrc`
|
||||
|
||||
**Package Manager:**
|
||||
|
||||
- npm - Monorepo workspace management via npm workspaces
|
||||
- Lockfile: `package-lock.json` (present)
|
||||
|
||||
## Frameworks
|
||||
|
||||
**Core - Frontend:**
|
||||
|
||||
- React 19.2.3 - UI framework with hooks and concurrent features
|
||||
- Vite 7.3.0 - Build tool and dev server (`apps/ui/vite.config.ts`)
|
||||
- Electron 39.2.7 - Desktop application runtime (`apps/ui/package.json`)
|
||||
- TanStack Router 1.141.6 - File-based routing (React)
|
||||
- Zustand 5.0.9 - State management (lightweight alternative to Redux)
|
||||
- TanStack Query (React Query) 5.90.17 - Server state management
|
||||
|
||||
**Core - Backend:**
|
||||
|
||||
- Express 5.2.1 - HTTP server framework (`apps/server/package.json`)
|
||||
- WebSocket (ws) 8.18.3 - Real-time bidirectional communication
|
||||
- Claude Agent SDK (@anthropic-ai/claude-agent-sdk) 0.1.76 - AI provider integration
|
||||
|
||||
**Testing:**
|
||||
|
||||
- Playwright 1.57.0 - End-to-end testing (`apps/ui` E2E tests)
|
||||
- Vitest 4.0.16 - Unit testing framework (runs on all packages and server)
|
||||
- @vitest/ui 4.0.16 - Visual test runner UI
|
||||
- @vitest/coverage-v8 4.0.16 - Code coverage reporting
|
||||
|
||||
**Build/Dev:**
|
||||
|
||||
- electron-builder 26.0.12 - Electron app packaging and distribution
|
||||
- @vitejs/plugin-react 5.1.2 - Vite React support
|
||||
- vite-plugin-electron 0.29.0 - Vite plugin for Electron main process
|
||||
- vite-plugin-electron-renderer 0.14.6 - Vite plugin for Electron renderer
|
||||
- ESLint 9.39.2 - Code linting (`apps/ui`)
|
||||
- @typescript-eslint/eslint-plugin 8.50.0 - TypeScript ESLint rules
|
||||
- Prettier 3.7.4 - Code formatting (root-level config)
|
||||
- Tailwind CSS 4.1.18 - Utility-first CSS framework
|
||||
- @tailwindcss/vite 4.1.18 - Tailwind Vite integration
|
||||
|
||||
**UI Components & Libraries:**
|
||||
|
||||
- Radix UI - Unstyled accessible component library (@radix-ui packages)
|
||||
- react-dropdown-menu 2.1.16
|
||||
- react-dialog 1.1.15
|
||||
- react-select 2.2.6
|
||||
- react-tooltip 1.2.8
|
||||
- react-tabs 1.1.13
|
||||
- react-collapsible 1.1.12
|
||||
- react-checkbox 1.3.3
|
||||
- react-radio-group 1.3.8
|
||||
- react-popover 1.1.15
|
||||
- react-slider 1.3.6
|
||||
- react-switch 1.2.6
|
||||
- react-scroll-area 1.2.10
|
||||
- react-label 2.1.8
|
||||
- Lucide React 0.562.0 - Icon library
|
||||
- Geist 1.5.1 - Design system UI library
|
||||
- Sonner 2.0.7 - Toast notifications
|
||||
|
||||
**Code Editor & Terminal:**
|
||||
|
||||
- @uiw/react-codemirror 4.25.4 - Code editor React component
|
||||
- CodeMirror (@codemirror packages) 6.x - Editor toolkit
|
||||
- xterm.js (@xterm/xterm) 5.5.0 - Terminal emulator
|
||||
- @xterm/addon-fit 0.10.0 - Fit addon for terminal
|
||||
- @xterm/addon-search 0.15.0 - Search addon for terminal
|
||||
- @xterm/addon-web-links 0.11.0 - Web links addon
|
||||
- @xterm/addon-webgl 0.18.0 - WebGL renderer for terminal
|
||||
|
||||
**Diagram/Graph Visualization:**
|
||||
|
||||
- @xyflow/react 12.10.0 - React flow diagram library
|
||||
- dagre 0.8.5 - Graph layout algorithms
|
||||
|
||||
**Markdown/Content Rendering:**
|
||||
|
||||
- react-markdown 10.1.0 - Markdown parser and renderer
|
||||
- remark-gfm 4.0.1 - GitHub Flavored Markdown support
|
||||
- rehype-raw 7.0.0 - Raw HTML support in markdown
|
||||
- rehype-sanitize 6.0.0 - HTML sanitization
|
||||
|
||||
**Data Validation & Parsing:**
|
||||
|
||||
- zod 3.24.1 or 4.0.0 - Schema validation and TypeScript type inference
|
||||
|
||||
**Utilities:**
|
||||
|
||||
- class-variance-authority 0.7.1 - CSS variant utilities
|
||||
- clsx 2.1.1 - Conditional className utility
|
||||
- cmdk 1.1.1 - Command menu/palette
|
||||
- tailwind-merge 3.4.0 - Tailwind CSS conflict resolution
|
||||
- usehooks-ts 3.1.1 - TypeScript React hooks
|
||||
- @dnd-kit (drag-and-drop) 6.3.1 - Drag and drop library
|
||||
|
||||
**Font Libraries:**
|
||||
|
||||
- @fontsource - Web font packages (Cascadia Code, Fira Code, IBM Plex, Inconsolata, Inter, etc.)
|
||||
|
||||
**Development Utilities:**
|
||||
|
||||
- cross-spawn 7.0.6 - Cross-platform process spawning
|
||||
- dotenv 17.2.3 - Environment variable loading
|
||||
- tsx 4.21.0 - TypeScript execution for Node.js
|
||||
- tree-kill 1.2.2 - Process tree killer utility
|
||||
- node-pty 1.1.0-beta41 - PTY/terminal interface for Node.js
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
**Critical - AI/Agent Integration:**
|
||||
|
||||
- @anthropic-ai/claude-agent-sdk 0.1.76 - Core Claude AI provider
|
||||
- @github/copilot-sdk 0.1.16 - GitHub Copilot integration
|
||||
- @openai/codex-sdk 0.77.0 - OpenAI Codex/GPT-4 integration
|
||||
- @modelcontextprotocol/sdk 1.25.2 - Model Context Protocol servers
|
||||
|
||||
**Infrastructure - Internal Packages:**
|
||||
|
||||
- @automaker/types 1.0.0 - Shared TypeScript type definitions
|
||||
- @automaker/utils 1.0.0 - Logging, error handling, utilities
|
||||
- @automaker/platform 1.0.0 - Path management, security, process spawning
|
||||
- @automaker/prompts 1.0.0 - AI prompt templates
|
||||
- @automaker/model-resolver 1.0.0 - Claude model alias resolution
|
||||
- @automaker/dependency-resolver 1.0.0 - Feature dependency ordering
|
||||
- @automaker/git-utils 1.0.0 - Git operations & worktree management
|
||||
- @automaker/spec-parser 1.0.0 - Project specification parsing
|
||||
|
||||
**Server Utilities:**
|
||||
|
||||
- express 5.2.1 - Web framework
|
||||
- cors 2.8.5 - CORS middleware
|
||||
- morgan 1.10.1 - HTTP request logger
|
||||
- cookie-parser 1.4.7 - Cookie parsing middleware
|
||||
- yaml 2.7.0 - YAML parsing and generation
|
||||
|
||||
**Type Definitions:**
|
||||
|
||||
- @types/express 5.0.6
|
||||
- @types/node 22.19.3
|
||||
- @types/react 19.2.7
|
||||
- @types/react-dom 19.2.3
|
||||
- @types/dagre 0.7.53
|
||||
- @types/ws 8.18.1
|
||||
- @types/cookie 0.6.0
|
||||
- @types/cookie-parser 1.4.10
|
||||
- @types/cors 2.8.19
|
||||
- @types/morgan 1.9.10
|
||||
|
||||
**Optional Dependencies (Platform-specific):**
|
||||
|
||||
- lightningcss (various platforms) 1.29.2 - CSS parser (alternate to PostCSS)
|
||||
- dmg-license 1.0.11 - DMG license dialog for macOS
|
||||
|
||||
## Configuration
|
||||
|
||||
**Environment:**
|
||||
|
||||
- `.env` and `.env.example` files in `apps/server/` and `apps/ui/`
|
||||
- `dotenv` library loads variables from `.env` files
|
||||
- Key env vars:
|
||||
- `ANTHROPIC_API_KEY` - Claude API authentication
|
||||
- `OPENAI_API_KEY` - OpenAI/Codex authentication
|
||||
- `GITHUB_TOKEN` - GitHub API access
|
||||
- `ANTHROPIC_BASE_URL` - Custom Claude endpoint (optional)
|
||||
- `HOST` - Server bind address (default: 0.0.0.0)
|
||||
- `HOSTNAME` - Hostname for URLs (default: localhost)
|
||||
- `PORT` - Server port (default: 3008)
|
||||
- `DATA_DIR` - Data storage directory (default: ./data)
|
||||
- `ALLOWED_ROOT_DIRECTORY` - Restrict file operations
|
||||
- `AUTOMAKER_MOCK_AGENT` - Enable mock agent for testing
|
||||
- `AUTOMAKER_AUTO_LOGIN` - Skip login in dev (disabled in production)
|
||||
- `VITE_HOSTNAME` - Frontend API hostname
|
||||
|
||||
**Build:**
|
||||
|
||||
- `apps/ui/electron-builder.config.json` or `apps/ui/package.json` build config
|
||||
- Electron builder targets:
|
||||
- macOS: DMG and ZIP
|
||||
- Windows: NSIS installer
|
||||
- Linux: AppImage, DEB, RPM
|
||||
- Vite config: `apps/ui/vite.config.ts`, `apps/server/tsconfig.json`
|
||||
- TypeScript config: `tsconfig.json` files in each package
|
||||
|
||||
## Platform Requirements
|
||||
|
||||
**Development:**
|
||||
|
||||
- Node.js 22.x
|
||||
- npm (included with Node.js)
|
||||
- Git (for worktree operations)
|
||||
- Python (optional, for some dev scripts)
|
||||
|
||||
**Production:**
|
||||
|
||||
- Electron desktop app: Windows, macOS, Linux
|
||||
- Web browser: Modern Chromium-based browsers
|
||||
- Server: Any platform supporting Node.js 22.x
|
||||
|
||||
**Deployment Target:**
|
||||
|
||||
- Local desktop (Electron)
|
||||
- Local web server (Express + Vite)
|
||||
- Remote server deployment (Docker, systemd, or other orchestration)
|
||||
|
||||
---
|
||||
|
||||
_Stack analysis: 2026-01-27_
|
||||
340
.planning/codebase/STRUCTURE.md
Normal file
340
.planning/codebase/STRUCTURE.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# Codebase Structure
|
||||
|
||||
**Analysis Date:** 2026-01-27
|
||||
|
||||
## Directory Layout
|
||||
|
||||
```
|
||||
automaker/
|
||||
├── apps/ # Application packages
|
||||
│ ├── ui/ # React + Electron frontend (port 3007)
|
||||
│ │ ├── src/
|
||||
│ │ │ ├── main.ts # Electron/Vite entry point
|
||||
│ │ │ ├── app.tsx # Root React component (splash, router)
|
||||
│ │ │ ├── renderer.tsx # Electron renderer entry
|
||||
│ │ │ ├── routes/ # TanStack Router file-based routes
|
||||
│ │ │ ├── components/ # React components (views, dialogs, UI, layout)
|
||||
│ │ │ ├── store/ # Zustand state management
|
||||
│ │ │ ├── hooks/ # Custom React hooks
|
||||
│ │ │ ├── lib/ # Utilities (API client, electron, queries, etc.)
|
||||
│ │ │ ├── electron/ # Electron main & preload process files
|
||||
│ │ │ ├── config/ # UI configuration (fonts, themes, routes)
|
||||
│ │ │ └── styles/ # CSS and theme files
|
||||
│ │ ├── public/ # Static assets
|
||||
│ │ └── tests/ # E2E Playwright tests
|
||||
│ │
|
||||
│ └── server/ # Express backend (port 3008)
|
||||
│ ├── src/
|
||||
│ │ ├── index.ts # Express app initialization, route mounting
|
||||
│ │ ├── routes/ # REST API endpoints (30+ route folders)
|
||||
│ │ ├── services/ # Business logic services
|
||||
│ │ ├── providers/ # AI model provider implementations
|
||||
│ │ ├── lib/ # Utilities (events, auth, helpers, etc.)
|
||||
│ │ ├── middleware/ # Express middleware
|
||||
│ │ └── types/ # Server-specific type definitions
|
||||
│ └── tests/ # Unit tests (Vitest)
|
||||
│
|
||||
├── libs/ # Shared npm packages (@automaker/*)
|
||||
│ ├── types/ # @automaker/types (no dependencies)
|
||||
│ │ └── src/
|
||||
│ │ ├── index.ts # Main export with all type definitions
|
||||
│ │ ├── feature.ts # Feature, FeatureStatus, etc.
|
||||
│ │ ├── provider.ts # Provider interfaces, model definitions
|
||||
│ │ ├── settings.ts # Global and project settings types
|
||||
│ │ ├── event.ts # Event types for real-time updates
|
||||
│ │ ├── session.ts # AgentSession, conversation types
|
||||
│ │ ├── model*.ts # Model-specific types (cursor, codex, gemini, etc.)
|
||||
│ │ └── ... 20+ more type files
|
||||
│ │
|
||||
│ ├── utils/ # @automaker/utils (logging, errors, images, context)
|
||||
│ │ └── src/
|
||||
│ │ ├── logger.ts # createLogger() with LogLevel enum
|
||||
│ │ ├── errors.ts # classifyError(), error types
|
||||
│ │ ├── image-utils.ts # Image processing, base64 encoding
|
||||
│ │ ├── context-loader.ts # loadContextFiles() for AI prompts
|
||||
│ │ └── ... more utilities
|
||||
│ │
|
||||
│ ├── platform/ # @automaker/platform (paths, security, OS)
|
||||
│ │ └── src/
|
||||
│ │ ├── index.ts # Path getters (getFeatureDir, getFeaturesDir, etc.)
|
||||
│ │ ├── secure-fs.ts # Secure filesystem operations
|
||||
│ │ └── config/ # Claude auth detection, allowed paths
|
||||
│ │
|
||||
│ ├── prompts/ # @automaker/prompts (AI prompt templates)
|
||||
│ │ └── src/
|
||||
│ │ ├── index.ts # Main prompts export
|
||||
│ │ └── *-prompt.ts # Prompt templates for different features
|
||||
│ │
|
||||
│ ├── model-resolver/ # @automaker/model-resolver
|
||||
│ │ └── src/
|
||||
│ │ └── index.ts # resolveModelString() for model aliases
|
||||
│ │
|
||||
│ ├── dependency-resolver/ # @automaker/dependency-resolver
|
||||
│ │ └── src/
|
||||
│ │ └── index.ts # Resolve feature dependencies
|
||||
│ │
|
||||
│ ├── git-utils/ # @automaker/git-utils (git operations)
|
||||
│ │ └── src/
|
||||
│ │ ├── index.ts # getGitRepositoryDiffs(), worktree management
|
||||
│ │ └── ... git helpers
|
||||
│ │
|
||||
│ ├── spec-parser/ # @automaker/spec-parser
|
||||
│ │ └── src/
|
||||
│ │ └── ... spec parsing utilities
|
||||
│ │
|
||||
│ └── tsconfig.base.json # Base TypeScript config for all packages
|
||||
│
|
||||
├── .automaker/ # Project data directory (created by app)
|
||||
│ ├── features/ # Feature storage
|
||||
│ │ └── {featureId}/
|
||||
│ │ ├── feature.json # Feature metadata and content
|
||||
│ │ ├── agent-output.md # Agent execution results
|
||||
│ │ └── images/ # Feature images
|
||||
│ ├── context/ # Context files (CLAUDE.md, etc.)
|
||||
│ ├── settings.json # Per-project settings
|
||||
│ ├── spec.md # Project specification
|
||||
│ └── analysis.json # Project structure analysis
|
||||
│
|
||||
├── data/ # Global data directory (default, configurable)
|
||||
│ ├── settings.json # Global settings, profiles
|
||||
│ ├── credentials.json # Encrypted API keys
|
||||
│ ├── sessions-metadata.json # Chat session metadata
|
||||
│ └── agent-sessions/ # Conversation histories
|
||||
│
|
||||
├── .planning/ # Generated documentation by GSD orchestrator
|
||||
│ └── codebase/ # Codebase analysis documents
|
||||
│ ├── ARCHITECTURE.md # Architecture patterns and layers
|
||||
│ ├── STRUCTURE.md # This file
|
||||
│ ├── STACK.md # Technology stack
|
||||
│ ├── INTEGRATIONS.md # External API integrations
|
||||
│ ├── CONVENTIONS.md # Code style and naming
|
||||
│ ├── TESTING.md # Testing patterns
|
||||
│ └── CONCERNS.md # Technical debt and issues
|
||||
│
|
||||
├── .github/ # GitHub Actions workflows
|
||||
├── scripts/ # Build and utility scripts
|
||||
├── tests/ # Test data and utilities
|
||||
├── docs/ # Documentation
|
||||
├── package.json # Root workspace config
|
||||
├── package-lock.json # Lock file
|
||||
├── CLAUDE.md # Project instructions for Claude Code
|
||||
├── DEVELOPMENT_WORKFLOW.md # Development guidelines
|
||||
└── README.md # Project overview
|
||||
```
|
||||
|
||||
## Directory Purposes
|
||||
|
||||
**apps/ui/:**
|
||||
|
||||
- Purpose: React frontend for desktop (Electron) and web modes
|
||||
- Build system: Vite 7 with TypeScript
|
||||
- Styling: Tailwind CSS 4
|
||||
- State: Zustand 5 with API persistence
|
||||
- Routing: TanStack Router with file-based structure
|
||||
- Desktop: Electron 39 with preload IPC bridge
|
||||
|
||||
**apps/server/:**
|
||||
|
||||
- Purpose: Express backend API and service layer
|
||||
- Build system: TypeScript → JavaScript
|
||||
- Runtime: Node.js 18+
|
||||
- WebSocket: ws library for real-time streaming
|
||||
- Process management: node-pty for terminal isolation
|
||||
|
||||
**libs/types/:**
|
||||
|
||||
- Purpose: Central type definitions (no dependencies, fast import)
|
||||
- Used by: All other packages and apps
|
||||
- Pattern: Single namespace export from index.ts
|
||||
- Build: Compiled to ESM only
|
||||
|
||||
**libs/utils/:**
|
||||
|
||||
- Purpose: Shared utilities for logging, errors, file operations, image processing
|
||||
- Used by: Server, UI, other libraries
|
||||
- Notable: `createLogger()`, `classifyError()`, `loadContextFiles()`, `readImageAsBase64()`
|
||||
|
||||
**libs/platform/:**
|
||||
|
||||
- Purpose: OS-agnostic path management and security enforcement
|
||||
- Used by: Server services for file operations
|
||||
- Notable: Path normalization, allowed directory enforcement, Claude auth detection
|
||||
|
||||
**libs/prompts/:**
|
||||
|
||||
- Purpose: AI prompt templates injected into agent context
|
||||
- Used by: AgentService when executing features
|
||||
- Pattern: Function exports that return prompt strings
|
||||
|
||||
## Key File Locations
|
||||
|
||||
**Entry Points:**
|
||||
|
||||
**Server:**
|
||||
|
||||
- `apps/server/src/index.ts`: Express server initialization, route mounting, WebSocket setup
|
||||
|
||||
**UI (Web):**
|
||||
|
||||
- `apps/ui/src/main.ts`: Vite entry point
|
||||
- `apps/ui/src/app.tsx`: Root React component
|
||||
|
||||
**UI (Electron):**
|
||||
|
||||
- `apps/ui/src/main.ts`: Vite entry point
|
||||
- `apps/ui/src/electron/main-process.ts`: Electron main process
|
||||
- `apps/ui/src/preload.ts`: Electron preload script for IPC bridge
|
||||
|
||||
**Configuration:**
|
||||
|
||||
- `apps/server/src/index.ts`: PORT, HOST, HOSTNAME, DATA_DIR env vars
|
||||
- `apps/ui/src/config/`: Theme options, fonts, model aliases
|
||||
- `libs/types/src/settings.ts`: Settings schema
|
||||
- `.env.local`: Local development overrides (git-ignored)
|
||||
|
||||
**Core Logic:**
|
||||
|
||||
**Server:**
|
||||
|
||||
- `apps/server/src/services/agent-service.ts`: AI agent execution engine (31KB)
|
||||
- `apps/server/src/services/auto-mode-service.ts`: Feature batching and automation (216KB - largest)
|
||||
- `apps/server/src/services/feature-loader.ts`: Feature persistence and loading
|
||||
- `apps/server/src/services/settings-service.ts`: Settings management
|
||||
- `apps/server/src/providers/provider-factory.ts`: AI provider selection
|
||||
|
||||
**UI:**
|
||||
|
||||
- `apps/ui/src/store/app-store.ts`: Global state (84KB - largest frontend file)
|
||||
- `apps/ui/src/lib/http-api-client.ts`: API client with auth (92KB)
|
||||
- `apps/ui/src/components/views/board-view.tsx`: Kanban board (70KB)
|
||||
- `apps/ui/src/routes/__root.tsx`: Root layout with session init (32KB)
|
||||
|
||||
**Testing:**
|
||||
|
||||
**E2E Tests:**
|
||||
|
||||
- `apps/ui/tests/`: Playwright tests organized by feature area
|
||||
- `settings/`, `features/`, `projects/`, `agent/`, `utils/`, `context/`
|
||||
|
||||
**Unit Tests:**
|
||||
|
||||
- `libs/*/tests/`: Package-specific Vitest tests
|
||||
- `apps/server/src/tests/`: Server integration tests
|
||||
|
||||
**Test Config:**
|
||||
|
||||
- `vitest.config.ts`: Root Vitest configuration
|
||||
- `apps/ui/playwright.config.ts`: Playwright configuration
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
**Files:**
|
||||
|
||||
- **Components:** PascalCase.tsx (e.g., `board-view.tsx`, `session-manager.tsx`)
|
||||
- **Services:** camelCase-service.ts (e.g., `agent-service.ts`, `settings-service.ts`)
|
||||
- **Hooks:** use-kebab-case.ts (e.g., `use-auto-mode.ts`, `use-settings-sync.ts`)
|
||||
- **Utilities:** camelCase.ts (e.g., `api-fetch.ts`, `log-parser.ts`)
|
||||
- **Routes:** kebab-case with index.ts pattern (e.g., `routes/agent/index.ts`)
|
||||
- **Tests:** _.test.ts or _.spec.ts (co-located with source)
|
||||
|
||||
**Directories:**
|
||||
|
||||
- **Feature domains:** kebab-case (e.g., `auto-mode/`, `event-history/`, `project-settings-view/`)
|
||||
- **Type categories:** kebab-case plural (e.g., `types/`, `services/`, `providers/`, `routes/`)
|
||||
- **Shared utilities:** kebab-case (e.g., `lib/`, `utils/`, `hooks/`)
|
||||
|
||||
**TypeScript:**
|
||||
|
||||
- **Types:** PascalCase (e.g., `Feature`, `AgentSession`, `ProviderMessage`)
|
||||
- **Interfaces:** PascalCase (e.g., `EventEmitter`, `ProviderFactory`)
|
||||
- **Enums:** PascalCase (e.g., `LogLevel`, `FeatureStatus`)
|
||||
- **Functions:** camelCase (e.g., `createLogger()`, `classifyError()`)
|
||||
- **Constants:** UPPER_SNAKE_CASE (e.g., `DEFAULT_TIMEOUT_MS`, `MAX_RETRIES`)
|
||||
- **Variables:** camelCase (e.g., `featureId`, `settingsService`)
|
||||
|
||||
## Where to Add New Code
|
||||
|
||||
**New Feature (end-to-end):**
|
||||
|
||||
- API Route: `apps/server/src/routes/{feature-name}/index.ts`
|
||||
- Service Logic: `apps/server/src/services/{feature-name}-service.ts`
|
||||
- UI Route: `apps/ui/src/routes/{feature-name}.tsx` (simple) or `{feature-name}/` (complex with subdir)
|
||||
- Store: `apps/ui/src/store/{feature-name}-store.ts` (if complex state)
|
||||
- Tests: `apps/ui/tests/{feature-name}/` or `apps/server/src/tests/`
|
||||
|
||||
**New Component/Module:**
|
||||
|
||||
- View Components: `apps/ui/src/components/views/{component-name}/`
|
||||
- Dialog Components: `apps/ui/src/components/dialogs/{dialog-name}.tsx`
|
||||
- Shared Components: `apps/ui/src/components/shared/` or `components/ui/` (shadcn)
|
||||
- Layout Components: `apps/ui/src/components/layout/`
|
||||
|
||||
**Utilities:**
|
||||
|
||||
- New Library: Create in `libs/{package-name}/` with package.json and tsconfig.json
|
||||
- Server Utilities: `apps/server/src/lib/{utility-name}.ts`
|
||||
- Shared Utilities: Extend `libs/utils/src/` or create new lib if self-contained
|
||||
- UI Utilities: `apps/ui/src/lib/{utility-name}.ts`
|
||||
|
||||
**New Provider (AI Model):**
|
||||
|
||||
- Implementation: `apps/server/src/providers/{provider-name}-provider.ts`
|
||||
- Types: Add to `libs/types/src/{provider-name}-models.ts`
|
||||
- Model Resolver: Update `libs/model-resolver/src/index.ts` with model alias mapping
|
||||
- Settings: Update `libs/types/src/settings.ts` for provider-specific config
|
||||
|
||||
## Special Directories
|
||||
|
||||
**apps/ui/electron/:**
|
||||
|
||||
- Purpose: Electron-specific code (main process, IPC handlers, native APIs)
|
||||
- Generated: Yes (preload.ts)
|
||||
- Committed: Yes
|
||||
|
||||
**apps/ui/public/**
|
||||
|
||||
- Purpose: Static assets (sounds, images, icons)
|
||||
- Generated: No
|
||||
- Committed: Yes
|
||||
|
||||
**apps/ui/dist/:**
|
||||
|
||||
- Purpose: Built web application
|
||||
- Generated: Yes
|
||||
- Committed: No (.gitignore)
|
||||
|
||||
**apps/ui/dist-electron/:**
|
||||
|
||||
- Purpose: Built Electron app bundle
|
||||
- Generated: Yes
|
||||
- Committed: No (.gitignore)
|
||||
|
||||
**.automaker/features/{featureId}/:**
|
||||
|
||||
- Purpose: Per-feature persistent storage
|
||||
- Structure: feature.json, agent-output.md, images/
|
||||
- Generated: Yes (at runtime)
|
||||
- Committed: Yes (tracked in project git)
|
||||
|
||||
**data/:**
|
||||
|
||||
- Purpose: Global data directory (global settings, credentials, sessions)
|
||||
- Generated: Yes (created at first run)
|
||||
- Committed: No (.gitignore)
|
||||
- Configurable: Via DATA_DIR env var
|
||||
|
||||
**node_modules/:**
|
||||
|
||||
- Purpose: Installed dependencies
|
||||
- Generated: Yes
|
||||
- Committed: No (.gitignore)
|
||||
|
||||
**dist/**, **build/:**
|
||||
|
||||
- Purpose: Build artifacts
|
||||
- Generated: Yes
|
||||
- Committed: No (.gitignore)
|
||||
|
||||
---
|
||||
|
||||
_Structure analysis: 2026-01-27_
|
||||
389
.planning/codebase/TESTING.md
Normal file
389
.planning/codebase/TESTING.md
Normal file
@@ -0,0 +1,389 @@
|
||||
# Testing Patterns
|
||||
|
||||
**Analysis Date:** 2026-01-27
|
||||
|
||||
## Test Framework
|
||||
|
||||
**Runner:**
|
||||
|
||||
- Vitest 4.0.16 (for unit and integration tests)
|
||||
- Playwright (for E2E tests)
|
||||
- Config: `apps/server/vitest.config.ts`, `libs/*/vitest.config.ts`, `apps/ui/playwright.config.ts`
|
||||
|
||||
**Assertion Library:**
|
||||
|
||||
- Vitest built-in expect assertions
|
||||
- API: `expect().toBe()`, `expect().toEqual()`, `expect().toHaveLength()`, `expect().toHaveProperty()`
|
||||
|
||||
**Run Commands:**
|
||||
|
||||
```bash
|
||||
npm run test # E2E tests (Playwright, headless)
|
||||
npm run test:headed # E2E tests with browser visible
|
||||
npm run test:packages # All shared package unit tests (vitest)
|
||||
npm run test:server # Server unit tests (vitest run)
|
||||
npm run test:server:coverage # Server tests with coverage report
|
||||
npm run test:all # All tests (packages + server)
|
||||
npm run test:unit # Vitest run (all projects)
|
||||
npm run test:unit:watch # Vitest watch mode
|
||||
```
|
||||
|
||||
## Test File Organization
|
||||
|
||||
**Location:**
|
||||
|
||||
- Co-located with source: `src/module.ts` has `tests/unit/module.test.ts`
|
||||
- Server tests: `apps/server/tests/` (separate directory)
|
||||
- Library tests: `libs/*/tests/` (each package)
|
||||
- E2E tests: `apps/ui/tests/` (Playwright)
|
||||
|
||||
**Naming:**
|
||||
|
||||
- Pattern: `{moduleName}.test.ts` for unit tests
|
||||
- Pattern: `{moduleName}.spec.ts` for specification tests
|
||||
- Glob pattern: `tests/**/*.test.ts`, `tests/**/*.spec.ts`
|
||||
|
||||
**Structure:**
|
||||
|
||||
```
|
||||
apps/server/
|
||||
├── tests/
|
||||
│ ├── setup.ts # Global test setup
|
||||
│ ├── unit/
|
||||
│ │ ├── providers/ # Provider tests
|
||||
│ │ │ ├── claude-provider.test.ts
|
||||
│ │ │ ├── codex-provider.test.ts
|
||||
│ │ │ └── base-provider.test.ts
|
||||
│ │ └── services/
|
||||
│ └── utils/
|
||||
│ └── helpers.ts # Test utilities
|
||||
└── src/
|
||||
|
||||
libs/platform/
|
||||
├── tests/
|
||||
│ ├── paths.test.ts
|
||||
│ ├── security.test.ts
|
||||
│ ├── subprocess.test.ts
|
||||
│ └── node-finder.test.ts
|
||||
└── src/
|
||||
```
|
||||
|
||||
## Test Structure
|
||||
|
||||
**Suite Organization:**
|
||||
|
||||
```typescript
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { FeatureLoader } from '@/services/feature-loader.js';
|
||||
|
||||
describe('feature-loader.ts', () => {
|
||||
let featureLoader: FeatureLoader;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
featureLoader = new FeatureLoader();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Cleanup resources
|
||||
});
|
||||
|
||||
describe('methodName', () => {
|
||||
it('should do specific thing', () => {
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Patterns:**
|
||||
|
||||
- Setup pattern: `beforeEach()` initializes test instance, clears mocks
|
||||
- Teardown pattern: `afterEach()` cleans up temp directories, removes created files
|
||||
- Assertion pattern: one logical assertion per test (or multiple closely related)
|
||||
- Test isolation: each test runs with fresh setup
|
||||
|
||||
## Mocking
|
||||
|
||||
**Framework:**
|
||||
|
||||
- Vitest `vi` module: `vi.mock()`, `vi.mocked()`, `vi.clearAllMocks()`
|
||||
- Mock patterns: module mocking, function spying, return value mocking
|
||||
|
||||
**Patterns:**
|
||||
|
||||
Module mocking:
|
||||
|
||||
```typescript
|
||||
vi.mock('@anthropic-ai/claude-agent-sdk');
|
||||
// In test:
|
||||
vi.mocked(sdk.query).mockReturnValue(
|
||||
(async function* () {
|
||||
yield { type: 'text', text: 'Response 1' };
|
||||
})()
|
||||
);
|
||||
```
|
||||
|
||||
Async generator mocking (for streaming APIs):
|
||||
|
||||
```typescript
|
||||
const generator = provider.executeQuery({
|
||||
prompt: 'Hello',
|
||||
model: 'claude-opus-4-5-20251101',
|
||||
cwd: '/test',
|
||||
});
|
||||
const results = await collectAsyncGenerator(generator);
|
||||
```
|
||||
|
||||
Partial mocking with spies:
|
||||
|
||||
```typescript
|
||||
const provider = new TestProvider();
|
||||
const spy = vi.spyOn(provider, 'getName');
|
||||
spy.mockReturnValue('mocked-name');
|
||||
```
|
||||
|
||||
**What to Mock:**
|
||||
|
||||
- External APIs (Claude SDK, GitHub SDK, cloud services)
|
||||
- File system operations (use temp directories instead when possible)
|
||||
- Network calls
|
||||
- Process execution
|
||||
- Time-dependent operations
|
||||
|
||||
**What NOT to Mock:**
|
||||
|
||||
- Core business logic (test the actual implementation)
|
||||
- Type definitions
|
||||
- Internal module dependencies (test integration with real services)
|
||||
- Standard library functions (fs, path, etc. - use fixtures instead)
|
||||
|
||||
## Fixtures and Factories
|
||||
|
||||
**Test Data:**
|
||||
|
||||
```typescript
|
||||
// Test helper for collecting async generator results
|
||||
async function collectAsyncGenerator<T>(generator: AsyncGenerator<T>): Promise<T[]> {
|
||||
const results: T[] = [];
|
||||
for await (const item of generator) {
|
||||
results.push(item);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// Temporary directory fixture
|
||||
beforeEach(async () => {
|
||||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'test-'));
|
||||
projectPath = path.join(tempDir, 'test-project');
|
||||
await fs.mkdir(projectPath, { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
try {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
} catch (error) {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Location:**
|
||||
|
||||
- Inline in test files for simple fixtures
|
||||
- `tests/utils/helpers.ts` for shared test utilities
|
||||
- Factory functions for complex test objects: `createTestProvider()`, `createMockFeature()`
|
||||
|
||||
## Coverage
|
||||
|
||||
**Requirements (Server):**
|
||||
|
||||
- Lines: 60%
|
||||
- Functions: 75%
|
||||
- Branches: 55%
|
||||
- Statements: 60%
|
||||
- Config: `apps/server/vitest.config.ts` with thresholds
|
||||
|
||||
**Excluded from Coverage:**
|
||||
|
||||
- Route handlers: tested via integration/E2E tests
|
||||
- Type re-exports
|
||||
- Middleware: tested via integration tests
|
||||
- Prompt templates
|
||||
- MCP integration: awaits MCP SDK integration tests
|
||||
- Provider CLI integrations: awaits integration tests
|
||||
|
||||
**View Coverage:**
|
||||
|
||||
```bash
|
||||
npm run test:server:coverage # Generate coverage report
|
||||
# Opens HTML report in: apps/server/coverage/index.html
|
||||
```
|
||||
|
||||
**Coverage Tools:**
|
||||
|
||||
- Provider: v8
|
||||
- Reporters: text, json, html, lcov
|
||||
- File inclusion: `src/**/*.ts`
|
||||
- File exclusion: `src/**/*.d.ts`, specific service files in thresholds
|
||||
|
||||
## Test Types
|
||||
|
||||
**Unit Tests:**
|
||||
|
||||
- Scope: Individual functions and methods
|
||||
- Approach: Test inputs → outputs with mocked dependencies
|
||||
- Location: `apps/server/tests/unit/`
|
||||
- Examples:
|
||||
- Provider executeQuery() with mocked SDK
|
||||
- Path construction functions with assertions
|
||||
- Error classification with different error types
|
||||
- Config validation with various inputs
|
||||
|
||||
**Integration Tests:**
|
||||
|
||||
- Scope: Multiple modules working together
|
||||
- Approach: Test actual service calls with real file system or temp directories
|
||||
- Pattern: Setup data → call method → verify results
|
||||
- Example: Feature loader reading/writing feature.json files
|
||||
- Example: Auto-mode service coordinating with multiple services
|
||||
|
||||
**E2E Tests:**
|
||||
|
||||
- Framework: Playwright
|
||||
- Scope: Full user workflows from UI
|
||||
- Location: `apps/ui/tests/`
|
||||
- Config: `apps/ui/playwright.config.ts`
|
||||
- Setup:
|
||||
- Backend server with mock agent enabled
|
||||
- Frontend Vite dev server
|
||||
- Sequential execution (workers: 1) to avoid auth conflicts
|
||||
- Screenshots/traces on failure
|
||||
- Auth: Global setup authentication in `tests/global-setup.ts`
|
||||
- Fixtures: `tests/e2e-fixtures/` for test project data
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Async Testing:**
|
||||
|
||||
```typescript
|
||||
it('should execute async operation', async () => {
|
||||
const result = await featureLoader.loadFeature(projectPath, featureId);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe(featureId);
|
||||
});
|
||||
|
||||
// For streams/generators:
|
||||
const generator = provider.executeQuery({ prompt, model, cwd });
|
||||
const results = await collectAsyncGenerator(generator);
|
||||
expect(results).toHaveLength(2);
|
||||
```
|
||||
|
||||
**Error Testing:**
|
||||
|
||||
```typescript
|
||||
it('should throw error when feature not found', async () => {
|
||||
await expect(featureLoader.getFeature(projectPath, 'nonexistent')).rejects.toThrow('not found');
|
||||
});
|
||||
|
||||
// Testing error classification:
|
||||
const errorInfo = classifyError(new Error('ENOENT'));
|
||||
expect(errorInfo.category).toBe('FileSystem');
|
||||
```
|
||||
|
||||
**Fixture Setup:**
|
||||
|
||||
```typescript
|
||||
it('should create feature with images', async () => {
|
||||
// Setup: create temp feature directory
|
||||
const featureDir = path.join(projectPath, '.automaker', 'features', featureId);
|
||||
await fs.mkdir(featureDir, { recursive: true });
|
||||
|
||||
// Act: perform operation
|
||||
const result = await featureLoader.updateFeature(projectPath, {
|
||||
id: featureId,
|
||||
imagePaths: ['/temp/image.png'],
|
||||
});
|
||||
|
||||
// Assert: verify file operations
|
||||
const migratedPath = path.join(featureDir, 'images', 'image.png');
|
||||
expect(fs.existsSync(migratedPath)).toBe(true);
|
||||
});
|
||||
```
|
||||
|
||||
**Mock Reset Pattern:**
|
||||
|
||||
```typescript
|
||||
// In vitest.config.ts:
|
||||
mockReset: true, // Reset all mocks before each test
|
||||
restoreMocks: true, // Restore original implementations
|
||||
clearMocks: true, // Clear mock call history
|
||||
|
||||
// In test:
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
delete process.env.ANTHROPIC_API_KEY;
|
||||
});
|
||||
```
|
||||
|
||||
## Test Configuration
|
||||
|
||||
**Vitest Config Patterns:**
|
||||
|
||||
Server config (`apps/server/vitest.config.ts`):
|
||||
|
||||
- Environment: node
|
||||
- Globals: true (describe/it without imports)
|
||||
- Setup files: `./tests/setup.ts`
|
||||
- Alias resolution: resolves `@automaker/*` to source files for mocking
|
||||
|
||||
Library config:
|
||||
|
||||
- Simpler setup: just environment and globals
|
||||
- Coverage with high thresholds (90%+ lines)
|
||||
|
||||
**Global Setup:**
|
||||
|
||||
```typescript
|
||||
// tests/setup.ts
|
||||
import { vi, beforeEach } from 'vitest';
|
||||
|
||||
process.env.NODE_ENV = 'test';
|
||||
process.env.DATA_DIR = '/tmp/test-data';
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
```
|
||||
|
||||
## Testing Best Practices
|
||||
|
||||
**Isolation:**
|
||||
|
||||
- Each test is independent (no state sharing)
|
||||
- Cleanup temp files in afterEach
|
||||
- Reset mocks and environment variables in beforeEach
|
||||
|
||||
**Clarity:**
|
||||
|
||||
- Descriptive test names: "should do X when Y condition"
|
||||
- One logical assertion per test
|
||||
- Clear arrange-act-assert structure
|
||||
|
||||
**Speed:**
|
||||
|
||||
- Mock external services
|
||||
- Use in-memory temp directories
|
||||
- Avoid real network calls
|
||||
- Sequential E2E tests to prevent conflicts
|
||||
|
||||
**Maintainability:**
|
||||
|
||||
- Use beforeEach/afterEach for common setup
|
||||
- Extract test helpers to `tests/utils/`
|
||||
- Keep test data simple and local
|
||||
- Mock consistently across tests
|
||||
|
||||
---
|
||||
|
||||
_Testing analysis: 2026-01-27_
|
||||
Reference in New Issue
Block a user