Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
c30cde2
docs: map existing codebase
Shironex Jan 27, 2026
4c1a26f
docs: initialize project
Shironex Jan 27, 2026
ae24767
chore: ignore planning docs from version control
Shironex Jan 27, 2026
94f455b
test(01-01): add characterization tests for ConcurrencyManager
Shironex Jan 27, 2026
b2b2d65
feat(01-01): extract ConcurrencyManager class from AutoModeService
Shironex Jan 27, 2026
55dcdaa
refactor(01-01): wire ConcurrencyManager into AutoModeService
Shironex Jan 27, 2026
1c91d6f
feat(01-03): create TypedEventBus class with tests
Shironex Jan 27, 2026
2a77407
feat(01-02): extract WorktreeResolver from AutoModeService
Shironex Jan 27, 2026
93a6c32
refactor(01-03): wire TypedEventBus into AutoModeService
Shironex Jan 27, 2026
e70f1d6
feat(01-02): extract FeatureStateManager from AutoModeService
Shironex Jan 27, 2026
8ef15f3
refactor(01-02): wire WorktreeResolver and FeatureStateManager into A…
Shironex Jan 27, 2026
13d0802
feat(02-01): create PlanApprovalService with timeout and recovery
Shironex Jan 27, 2026
1bc59c3
test(02-01): add PlanApprovalService tests
Shironex Jan 27, 2026
e06da72
refactor(02-01): wire PlanApprovalService into AutoModeService
Shironex Jan 27, 2026
52d87ba
feat(03-01): create SpecParser module with comprehensive tests
Shironex Jan 27, 2026
c2322e0
refactor(03-01): wire SpecParser into AutoModeService
Shironex Jan 27, 2026
8a59dbd
feat(03-02): create AgentExecutor class with core streaming logic
Shironex Jan 27, 2026
d003e9f
test(03-02): add AgentExecutor tests
Shironex Jan 27, 2026
a5c02e2
refactor(03-02): wire AgentExecutor into AutoModeService
Shironex Jan 27, 2026
758c6c0
refactor(03-03): wire runAgent() to delegate to AgentExecutor.execute()
Shironex Jan 27, 2026
927ae5e
test(03-03): add AgentExecutor execution tests
Shironex Jan 27, 2026
23d36c0
fix(03-03): fix type compatibility and cleanup unused imports
Shironex Jan 27, 2026
5b97267
feat(04-01): create PipelineOrchestrator with step execution and auto…
Shironex Jan 27, 2026
8ab77f6
test(04-01): add PipelineOrchestrator unit tests
Shironex Jan 27, 2026
eaa0312
refactor(04-02): wire PipelineOrchestrator into AutoModeService
Shironex Jan 27, 2026
2ad604e
test(04-02): add PipelineOrchestrator delegation and edge case tests
Shironex Jan 27, 2026
84461d6
refactor(04-02): remove duplicated pipeline methods from AutoModeService
Shironex Jan 27, 2026
b5624bb
feat(05-01): create AutoLoopCoordinator with loop lifecycle
Shironex Jan 27, 2026
74345ee
test(05-01): add AutoLoopCoordinator unit tests
Shironex Jan 27, 2026
3b2b1eb
feat(05-02): create ExecutionService with feature execution lifecycle
Shironex Jan 27, 2026
0a1c2cd
test(05-02): add ExecutionService unit tests
Shironex Jan 27, 2026
fd8bc71
feat(05-03): create RecoveryService with crash recovery logic
Shironex Jan 27, 2026
77ece9f
test(05-03): add RecoveryService unit tests
Shironex Jan 27, 2026
b59d2c6
refactor(05-03): wire coordination services into AutoModeService
Shironex Jan 27, 2026
236a23a
refactor(05-03): remove duplicated methods from AutoModeService
Shironex Jan 27, 2026
08f51a0
refactor(05-03): wire ExecutionService delegation in AutoModeService
Shironex Jan 27, 2026
da373ee
chore(06-01): create facade types and directory structure
Shironex Jan 30, 2026
68ea80b
feat(06-01): create AutoModeServiceFacade with all 23 methods
Shironex Jan 30, 2026
4ea35e1
chore(06-01): create index.ts with exports
Shironex Jan 30, 2026
8355eb7
refactor(06-02): migrate Batch 1 query-only routes to facade pattern
Shironex Jan 30, 2026
0ee28c5
refactor(06-02): migrate Batch 2 state change routes to facade pattern
Shironex Jan 30, 2026
ffbfd2b
refactor(06-03): migrate Batch 3 feature lifecycle routes to facade p…
Shironex Jan 30, 2026
5f9eacd
refactor(06-03): migrate Batch 4 complex routes to facade pattern
Shironex Jan 30, 2026
50c0b15
refactor(06-03): migrate Batch 5 secondary routes and wire router index
Shironex Jan 30, 2026
603cb63
refactor(06-04): delete auto-mode-service.ts monolith
Shironex Jan 30, 2026
622362f
refactor(06-04): trim 5 oversized services to under 500 lines
Shironex Jan 30, 2026
6ec9a25
refactor(06-04): extract types and condense agent-executor/pipeline-o…
Shironex Jan 30, 2026
47c2149
chore(deps): update lint-staged version and change node-gyp repositor…
Shironex Jan 30, 2026
188b08b
fix: lock file
Shironex Jan 30, 2026
6bb7b86
fix(facade): wire runAgentFn to AgentExecutor.execute
Shironex Jan 31, 2026
adddcf7
fix(agent-executor): restore wrench emoji in tool output format
Shironex Jan 31, 2026
bf82f92
fix(facade): pass previousContent to AgentExecutor for pipeline steps
Shironex Jan 31, 2026
5a5c56a
fix: address PR review issues for auto-mode refactor
Shironex Jan 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,6 @@ data/.api-key
data/credentials.json
data/
.codex/

# GSD planning docs (local-only)
.planning/
81 changes: 81 additions & 0 deletions .planning/PROJECT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# AutoModeService Refactoring

## What This Is

A comprehensive refactoring of the `auto-mode-service.ts` file (5k+ lines) into smaller, focused services with clear boundaries. This is an architectural cleanup of accumulated technical debt from rapid development, breaking the "god object" anti-pattern into maintainable, debuggable modules.

## Core Value

All existing auto-mode functionality continues working — features execute, pipelines flow, merges complete — while the codebase becomes maintainable.

## Requirements

### Validated

<!-- Existing functionality that must be preserved -->

- ✓ Single feature execution with AI agent — existing
- ✓ Concurrent execution with configurable limits — existing
- ✓ Pipeline orchestration (backlog → in-progress → approval → verified) — existing
- ✓ Git worktree isolation per feature — existing
- ✓ Automatic merging of completed work — existing
- ✓ Custom pipeline support — existing
- ✓ Test runner integration — existing
- ✓ Event streaming to frontend — existing

### Active

<!-- Refactoring goals -->

- [ ] No service file exceeds ~500 lines
- [ ] Each service has single, clear responsibility
- [ ] Service boundaries make debugging obvious
- [ ] Changes to one service don't risk breaking unrelated features
- [ ] Test coverage for critical paths

### Out of Scope

- New auto-mode features — this is cleanup, not enhancement
- UI changes — backend refactor only
- Performance optimization — maintain current performance, don't optimize
- Other service refactoring — focus on auto-mode-service.ts only

## Context

**Current state:** `apps/server/src/services/auto-mode-service.ts` is ~5700 lines handling:

- Worktree management (create, cleanup, track)
- Agent/task execution coordination
- Concurrency control and queue management
- Pipeline state machine (column transitions)
- Merge handling and conflict resolution
- Event emission for real-time updates

**Technical environment:**

- Express 5 backend, TypeScript
- Event-driven architecture via EventEmitter
- WebSocket streaming to React frontend
- Git worktrees via @automaker/git-utils
- Minimal existing test coverage

**Codebase analysis:** See `.planning/codebase/` for full architecture, conventions, and existing patterns.

## Constraints

- **Breaking changes**: Acceptable — other parts of the app can be updated to match new service interfaces
- **Test coverage**: Currently minimal — must add tests during refactoring to catch regressions
- **Incremental approach**: Required — can't do big-bang rewrite with everything critical
- **Existing patterns**: Follow conventions in `.planning/codebase/CONVENTIONS.md`

## Key Decisions

| Decision | Rationale | Outcome |
| ------------------------- | --------------------------------------------------- | --------- |
| Accept breaking changes | Allows cleaner interfaces, worth the migration cost | — Pending |
| Add tests during refactor | No existing safety net, need to build one | — Pending |
| Incremental extraction | Everything is critical, can't break it all at once | — Pending |

---

_Last updated: 2026-01-27 after initialization_
234 changes: 234 additions & 0 deletions .planning/codebase/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -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_
Loading
Loading