Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
152cf00
docs: map existing codebase
Shironex Jan 27, 2026
ef544e7
docs: initialize project
Shironex Jan 27, 2026
a0ea65d
chore: ignore planning docs from version control
Shironex Jan 27, 2026
70fc034
test(01-01): add characterization tests for ConcurrencyManager
Shironex Jan 27, 2026
b73ef9f
feat(01-01): extract ConcurrencyManager class from AutoModeService
Shironex Jan 27, 2026
c92c8e9
refactor(01-01): wire ConcurrencyManager into AutoModeService
Shironex Jan 27, 2026
3bcdc88
feat(01-03): create TypedEventBus class with tests
Shironex Jan 27, 2026
bc9dae0
feat(01-02): extract WorktreeResolver from AutoModeService
Shironex Jan 27, 2026
1eb2820
refactor(01-03): wire TypedEventBus into AutoModeService
Shironex Jan 27, 2026
6029e95
feat(01-02): extract FeatureStateManager from AutoModeService
Shironex Jan 27, 2026
18fd1c6
refactor(01-02): wire WorktreeResolver and FeatureStateManager into A…
Shironex Jan 27, 2026
8387b76
feat(02-01): create PlanApprovalService with timeout and recovery
Shironex Jan 27, 2026
58facb1
test(02-01): add PlanApprovalService tests
Shironex Jan 27, 2026
5dca97d
refactor(02-01): wire PlanApprovalService into AutoModeService
Shironex Jan 27, 2026
2fac438
feat(03-01): create SpecParser module with comprehensive tests
Shironex Jan 27, 2026
ec5179e
refactor(03-01): wire SpecParser into AutoModeService
Shironex Jan 27, 2026
25fa6fd
feat(03-02): create AgentExecutor class with core streaming logic
Shironex Jan 27, 2026
cbb45b6
test(03-02): add AgentExecutor tests
Shironex Jan 27, 2026
8f245e7
refactor(03-02): wire AgentExecutor into AutoModeService
Shironex Jan 27, 2026
e3a1c8c
refactor(03-03): wire runAgent() to delegate to AgentExecutor.execute()
Shironex Jan 27, 2026
b24839b
test(03-03): add AgentExecutor execution tests
Shironex Jan 27, 2026
4912d37
fix(03-03): fix type compatibility and cleanup unused imports
Shironex Jan 27, 2026
ba45587
feat(04-01): create PipelineOrchestrator with step execution and auto…
Shironex Jan 27, 2026
4f00b41
test(04-01): add PipelineOrchestrator unit tests
Shironex Jan 27, 2026
2e577bb
refactor(04-02): wire PipelineOrchestrator into AutoModeService
Shironex Jan 27, 2026
0cd149f
test(04-02): add PipelineOrchestrator delegation and edge case tests
Shironex Jan 27, 2026
7807255
refactor(04-02): remove duplicated pipeline methods from AutoModeService
Shironex Jan 27, 2026
94a8e09
feat(05-01): create AutoLoopCoordinator with loop lifecycle
Shironex Jan 27, 2026
2aa156e
test(05-01): add AutoLoopCoordinator unit tests
Shironex Jan 27, 2026
e0f785a
feat(05-02): create ExecutionService with feature execution lifecycle
Shironex Jan 27, 2026
71a0309
test(05-02): add ExecutionService unit tests
Shironex Jan 27, 2026
18624d1
feat(05-03): create RecoveryService with crash recovery logic
Shironex Jan 27, 2026
828d0a0
test(05-03): add RecoveryService unit tests
Shironex Jan 27, 2026
1b39e25
refactor(05-03): wire coordination services into AutoModeService
Shironex Jan 27, 2026
afa6039
refactor(05-03): remove duplicated methods from AutoModeService
Shironex Jan 27, 2026
1a7dd5d
refactor(05-03): wire ExecutionService delegation in AutoModeService
Shironex Jan 27, 2026
0383f85
chore(06-01): create facade types and directory structure
Shironex Jan 30, 2026
a048462
feat(06-01): create AutoModeServiceFacade with all 23 methods
Shironex Jan 30, 2026
1b32a6b
chore(06-01): create index.ts with exports
Shironex Jan 30, 2026
071af1b
refactor(06-02): migrate Batch 1 query-only routes to facade pattern
Shironex Jan 30, 2026
31f8afc
refactor(06-02): migrate Batch 2 state change routes to facade pattern
Shironex Jan 30, 2026
ade22ef
refactor(06-03): migrate Batch 3 feature lifecycle routes to facade p…
Shironex Jan 30, 2026
7bc1f68
refactor(06-03): migrate Batch 4 complex routes to facade pattern
Shironex Jan 30, 2026
7fd3d61
refactor(06-03): migrate Batch 5 secondary routes and wire router index
Shironex Jan 30, 2026
473f935
refactor(06-04): delete auto-mode-service.ts monolith
Shironex Jan 30, 2026
efd4284
refactor(06-04): trim 5 oversized services to under 500 lines
Shironex Jan 30, 2026
43309e3
refactor(06-04): extract types and condense agent-executor/pipeline-o…
Shironex Jan 30, 2026
0ed4494
chore(deps): update lint-staged version and change node-gyp repositor…
Shironex Jan 30, 2026
df10bcd
fix: lock file
Shironex Jan 30, 2026
28224e1
fix(facade): wire runAgentFn to AgentExecutor.execute
Shironex Jan 31, 2026
49bdaaa
fix(agent-executor): restore wrench emoji in tool output format
Shironex Jan 31, 2026
63b1a35
fix(facade): pass previousContent to AgentExecutor for pipeline steps
Shironex Jan 31, 2026
7c89923
fix: address PR review issues for auto-mode refactor
Shironex Jan 31, 2026
5ffbfb3
fix(server): Address PR #733 review feedback and fix cross-platform t…
Shironex Feb 2, 2026
bcc8542
Fix custom providers not passing model name properly
gsxdsm Feb 15, 2026
0f0f515
feat(auto-mode): implement facade caching and enhance error handling
gsxdsm Feb 15, 2026
0745832
refactor(auto-mode): convert getStatusForProject to async and enhance…
gsxdsm Feb 15, 2026
8542a32
refactor(auto-mode): enhance feature retrieval logic in facade and gl…
gsxdsm Feb 15, 2026
a3a5c9e
Merge remote-tracking branch 'upstream/v0.15.0rc' into refactor/auto-…
gsxdsm Feb 15, 2026
a935229
fix: enhance error handling in feature creation process
gsxdsm Feb 15, 2026
f459b73
fix: update kanban card status handling
gsxdsm Feb 15, 2026
41014f6
fix: resolve TypeScript errors after upstream merge
gsxdsm Feb 16, 2026
eed5e20
fix(agent-service): fallback to effectiveModel when requestedModel is…
gsxdsm Feb 16, 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,5 +95,8 @@ data/.api-key
data/credentials.json
data/
.codex/

# GSD planning docs (local-only)
.planning/
.mcp.json
.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