# Tasks ## Task 1: Create BackendAdapter interface and shared types - [x] 1.1 Create `src/backends/types.ts` with `BackendAdapter` interface, `BackendAdapterConfig`, `BackendEventResult`, `StreamCallback`, and `BackendName` type - [x] 1.2 Export all types from `src/backends/index.ts` barrel file ## Task 2: Implement ClaudeCodeBackend - [x] 2.1 Create `src/backends/claude-backend.ts` implementing `BackendAdapter` - [x] 2.2 Extract CLI spawning logic from `AgentRuntime.runClaude()` into `execute()` method with arg building for `-p`, `--output-format json`, `--dangerously-skip-permissions`, `--append-system-prompt-file`, `--allowedTools`, `--max-turns`, and `--resume` - [x] 2.3 Implement `validate()` to check CLI binary is executable - [x] 2.4 Implement JSON array output parser extracting `session_id` from `system/init` and `result` from `result` objects - [x] 2.5 Write property test: Claude backend required flags (Property 1) - [x] 🧪 PBT: *For any* prompt, system prompt, and tools list, generated args contain all required flags ## Task 3: Implement CodexBackend - [x] 3.1 Create `src/backends/codex-backend.ts` implementing `BackendAdapter` - [x] 3.2 Implement `execute()` with `codex exec` subcommand, `--json`, `--dangerously-bypass-approvals-and-sandbox`, `--cd`, and `codex exec resume ` for sessions - [x] 3.3 Implement newline-delimited JSON parser extracting final assistant message - [x] 3.4 Write property test: Codex backend required flags (Property 2) - [x] 🧪 PBT: *For any* prompt and working directory, generated args contain exec, --json, --dangerously-bypass-approvals-and-sandbox, and --cd ## Task 4: Implement GeminiBackend - [x] 4.1 Create `src/backends/gemini-backend.ts` implementing `BackendAdapter` - [x] 4.2 Implement `execute()` with prompt as positional arg, `--output-format json`, `--approval-mode yolo`, and `--resume` for sessions - [x] 4.3 Implement JSON output parser extracting response text - [x] 4.4 Write property test: Gemini backend required flags (Property 3) - [x] 🧪 PBT: *For any* prompt, generated args contain the prompt positionally, --output-format json, and --approval-mode yolo ## Task 5: Implement OpenCodeBackend - [x] 5.1 Create `src/backends/opencode-backend.ts` implementing `BackendAdapter` - [x] 5.2 Implement `execute()` with `opencode run` subcommand, `--format json`, `--model`, and `--session --continue` for sessions - [x] 5.3 Implement JSON event parser extracting final response text - [x] 5.4 Write property test: OpenCode backend required flags (Property 4) - [x] 🧪 PBT: *For any* prompt and optional model, generated args contain run, --format json, and --model when configured ## Task 6: Implement BackendRegistry - [x] 6.1 Create `src/backends/registry.ts` with `resolveBackendName()` and `createBackend()` functions - [x] 6.2 `resolveBackendName` accepts "claude", "codex", "gemini", "opencode", defaults to "claude" for undefined, throws for invalid values - [x] 6.3 `createBackend` instantiates the correct backend implementation from a `BackendName` - [x] 6.4 Write property test: Backend name resolution (Property 7) - [x] 🧪 PBT: *For any* string, resolveBackendName returns correct BackendName for valid values, "claude" for undefined, and throws for invalid ## Task 7: Cross-backend property tests - [x] 7.1 Write property test: Session resume args across backends (Property 5) - [x] 🧪 PBT: *For any* backend and session ID, session flags appear when ID is provided and are absent when not - [x] 7.2 Write property test: Output parsing extracts correct fields (Property 6) - [x] 🧪 PBT: *For any* valid backend-specific JSON output, parser produces BackendEventResult with correct responseText and sessionId - [x] 7.3 Write property test: Non-zero exit code produces error result (Property 8) - [x] 🧪 PBT: *For any* backend, non-zero exit code, and stderr string, result has isError=true and responseText contains stderr ## Task 8: Update GatewayConfig - [x] 8.1 Add `agentBackend`, `backendCliPath`, `backendModel`, `backendMaxTurns` fields to `GatewayConfig` interface in `src/config.ts` - [x] 8.2 Update `loadConfig()` to read `AGENT_BACKEND`, `BACKEND_CLI_PATH`, `BACKEND_MODEL`, `BACKEND_MAX_TURNS` env vars with defaults - [x] 8.3 Deprecate `claudeCliPath` field (keep for backward compat, map to `backendCliPath` when `AGENT_BACKEND=claude`) ## Task 9: Refactor AgentRuntime - [x] 9.1 Add `BackendAdapter` parameter to `AgentRuntime` constructor - [x] 9.2 Replace `executeClaude()` and `runClaude()` with calls to `this.backend.execute()` - [x] 9.3 Implement `BackendEventResult` → gateway `EventResult` mapping in a helper method - [x] 9.4 Remove `ClaudeJsonResponse` interface and Claude-specific parsing from `AgentRuntime` - [x] 9.5 Write property test: EventResult mapping preserves semantics (Property 9) - [x] 🧪 PBT: *For any* BackendEventResult and channel ID, mapping sets error or responseText correctly based on isError - [x] 9.6 Write property test: Session ID storage after backend execution (Property 10) - [x] 🧪 PBT: *For any* channel ID and BackendEventResult with sessionId, SessionManager contains that sessionId after processing ## Task 10: Startup validation and wiring - [x] 10.1 Update main entry point to call `resolveBackendName()` and `createBackend()` from config - [x] 10.2 Call `backend.validate()` at startup; log error with backend name and path, exit(1) on failure - [x] 10.3 Inject the `BackendAdapter` instance into `AgentRuntime` constructor - [x] 10.4 Write unit tests for startup validation flow (valid backend, invalid backend name, missing CLI binary) ## Task 11: Unit tests for edge cases - [x] 11.1 Write unit tests for each backend's `validate()` method (binary exists vs missing) - [x] 11.2 Write unit tests for timeout behavior (process killed after queryTimeoutMs) - [x] 11.3 Write unit tests for session corruption detection and cleanup - [x] 11.4 Write unit tests for default config values when env vars are unset - [x] 11.5 Write unit tests for unsupported option warning (e.g., ALLOWED_TOOLS on backends without tool filtering)