Orchestrata Ultimate / Specs / 025-code-generation-drivers

025-code-generation-drivers: Code Generation Drivers

The Code Generation Drivers package (orchestrata-drivers) provides a uniform async interface over multiple external code generation tools and LLM providers. A single Protocol (AsyncCodeDriver) is implemented by seven concrete drivers covering Claude Code CLI, Anthropic API (via Claude Code stdin pipe), Aider CLI, DeepSeek API, Qwen CLI, and three browser-based free-tier LLM web UIs (Qwen Chat, DeepSeek Chat, Kimi). A factory function (get_driver) selects the correct driver from a...

At a glance

Item Value
Spec directory specs/025-code-generation-drivers/
Status line in the spec Implemented
Requirement IDs defined 102
With a @traces citation in src/ 82 (80.4%)
With a @traces citation in tests/ 3 (2.9%)
Tracked files 6
RTM page 025-code-generation-drivers

Reading this spec

The Code Generation Drivers package gives a uniform async interface over several external code generation tools and LLM providers. One protocol, AsyncCodeDriver, is implemented by seven concrete drivers covering the Claude Code CLI, the Anthropic API, Aider, the DeepSeek API, the Qwen CLI and three browser-based free-tier LLM web UIs. It exists because the CodeDirector's swarm coordinator needs one interface to dispatch code generation to any backend, provider-selection logic was duplicated across callers, and browser automation complexity must stay out of business logic.

The scope is four user stories (unified code generation interface, browser-based free-tier LLM access, code artifact extraction, provider configuration routing) and twelve functional requirements, from the protocol and driver factory routing through binary detection, subprocess timeout enforcement, workspace file scanning, DeepSeek integration, browser session persistence, three-tier browser recovery, rate limiting, code extraction utilities, the unknown provider fallback and runtime protocol checkability. Requirement IDs use the REQ-025- prefix.

The key decisions are that AsyncCodeDriver defines execute(task, files, is_fix) returning a success flag and text; get_driver(volk, workspace) reads the Volk's provider from the LLM configuration and instantiates the right driver, so routing is configuration-driven; CLI drivers wrap external binaries with enforced timeouts; the browser driver uses Playwright headless Chromium with per-provider configuration; and browser sessions persist to JSON state files and recover through navigate, restart and re-authenticate escalation.

In the code, the package is orchestrata_ultimate/drivers. The largest tracers are orchestrata_ultimate/drivers/browser_driver, orchestrata_ultimate/drivers/claude_code_driver, orchestrata_ultimate/drivers/driver_factory, orchestrata_ultimate/drivers/claude_api_driver and orchestrata_ultimate/drivers/extraction. The per-requirement view is on the RTM page.

The spec's status line reads Implemented. It tracks 6 files and defines 102 requirement IDs. The full text follows below.

Measured coverage is 82 of 102 requirements cited by at least one @traces in src/ (80.4%), spread over 11 modules; the module citing the most of them is orchestrata_ultimate/drivers/browser_driver (22 requirements). In tests/, 3 requirements are cited by a test-side @traces.

Coverage gaps: 20 requirements have no citing symbol. The largest untraced groups are REQ-025-* (20). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (3 against 82).

Requirements

Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.

ID Done Requirement Traced by
REQ-025-001 no AsyncCodeDriver defined as runtime_checkable Protocol in base.py 1
REQ-025-002 no Protocol decorated with @traces(spec="025") for traceability 1
REQ-025-003 no execute(task, files, is_fix) method signature enforced on all drivers 2
REQ-025-004 no Return type is tuple[bool, str] — (success, output_text) 2
REQ-025-005 no files parameter accepts list[str] | None (optional, None by default) 1
REQ-025-006 no is_fix boolean parameter signals repair vs new generation invocation 1
REQ-025-007 no get_driver(volk, workspace) reads provider via get_volk_provider(volk) 1
REQ-025-008 no Default volk is J:Junior when no volk argument provided 1
REQ-025-009 no Workspace defaults to ORCHESTRATA_WORKSPACE env var if not provided 1
REQ-025-010 no Workspace falls back to /home/mohamed/workspace if env var unset 1
REQ-025-011 no Provider claude or anthropic routes to ClaudeAPIDriver 2
REQ-025-012 no Provider deepseek routes to DeepSeekCoderDriver 2
REQ-025-013 no Provider aider routes to AiderDriver 2
REQ-025-014 no Provider qwen or ollama routes to QwenDriver 2
REQ-025-015 no Provider qwen_browser routes to BrowserDriver(provider="qwen_chat") 2
REQ-025-016 no Provider deepseek_browser routes to BrowserDriver(provider="deepseek_chat") 2
REQ-025-017 no Provider kimi_browser routes to BrowserDriver(provider="kimi") 2
REQ-025-018 no Unrecognised provider logs a warning and falls back to ClaudeAPIDriver 1
REQ-025-019 no Binary located via shutil.which("claude") then fallback paths 2
REQ-025-020 no Fallback paths checked: ~/.local/bin/claude, /usr/bin/claude, /usr/local/bin/claude 2
REQ-025-021 no Command: claude --print --dangerously-skip-permissions <task> 2
REQ-025-022 no Output streamed line-by-line from stdout+stderr combined 1
REQ-025-023 no Timeout of 900 seconds enforced via asyncio.wait_for 2
REQ-025-024 no Non-zero exit code returns (False, output) 1
REQ-025-025 no Binary not found returns (False, "Claude Code CLI not found") 1
REQ-025-026 no Timeout returns (False, "Timed out after 900s") 1
REQ-025-027 no Task prompt delivered via stdin pipe (avoids E7 arg-list-too-long) 2
REQ-025-028 no Runs claude init --yes if CLAUDE.md absent from workspace 1
REQ-025-029 no Init skipped silently if CLAUDE.md already present 1
REQ-025-030 no Post-execution workspace scan enumerates created source files 1
REQ-025-031 no Scan covers extensions: .py, .toml, .cfg, .ini, .yaml, .yml none
REQ-025-032 no Scan skips directories: .venv, __pycache__, .git, node_modules, .claude, design none
REQ-025-033 no Returns (False, "No files generated") when scan finds no source files 1
REQ-025-034 no Timeout of 1200 seconds enforced via asyncio.wait_for 1
REQ-025-035 no Binary located via shutil.which("aider") then fallback paths 2
REQ-025-036 no Command: aider --message <task> --yes-always --no-auto-commits 2
REQ-025-037 no Each path in files appended as separate --file <path> argument 2
REQ-025-038 no Timeout of 300 seconds enforced 3
REQ-025-039 no Non-zero exit returns (False, output) 2
REQ-025-040 no Binary not found returns (False, "Aider CLI not found") 2
REQ-025-041 no API key read from DEEPSEEK_API_KEY environment variable none
REQ-025-042 no Missing API key returns (False, error_message) immediately none
REQ-025-043 no Uses model=deepseek-coder for code generation requests none
REQ-025-044 no Constructs system + user message pair for the API call 1
REQ-025-045 no API errors return (False, error_message) with error detail 1
REQ-025-046 no Binary located via shutil.which("qwen") then fallback paths 2
REQ-025-047 no Task passed as positional argument to the Qwen CLI none
REQ-025-048 no Timeout of 600 seconds enforced 2
REQ-025-049 no Non-zero exit returns (False, output) none
REQ-025-050 no Binary not found returns (False, "Qwen CLI not found") 1
REQ-025-051 no Uses playwright.async_api with headless Chromium 3
REQ-025-052 no headless parameter controls visible vs headless mode (default: True) 1
REQ-025-053 no Browser state persisted to .browser_state/<provider>_state.json under workspace 1
REQ-025-054 no Existing state file loaded via storage_state on launch 2
REQ-025-055 no close() saves storage state before closing browser 2
REQ-025-056 no Rate limit enforced: waits rate_limit_seconds minimum between requests 1
REQ-025-057 no Session expiry checked against max_session_minutes on each execute() 1
REQ-025-058 no Expired session triggers level-2 recovery (restart) before execute 1
REQ-025-059 no _session_start timestamp reset on each browser launch 2
REQ-025-060 no Max 3 recovery attempts per execute() call 1
REQ-025-061 no Level 1 recovery: navigate page back to base_url 1
REQ-025-062 no Level 2 recovery: close browser, wait 3 seconds, relaunch 1
REQ-025-063 no Level 1 failure escalates to level 2 automatically 1
REQ-025-064 no All attempts exhausted returns (False, "All recovery attempts exhausted") 1
REQ-025-065 no FILE: format instructions appended to every prompt 1
REQ-025-066 no File context included in prompt for non-fix tasks when files provided 1
REQ-025-067 no File context truncated at 5000 characters per file 1
REQ-025-068 no Files not found in workspace silently skipped in context 1
REQ-025-069 no extract_file_blocks called first on response text 1
REQ-025-070 no Falls back to extract_markdown_code_blocks when no FILE: blocks found 1
REQ-025-071 no No code blocks found returns (False, "No code blocks found in response") 1
REQ-025-072 no Extracted FILE: blocks written to workspace disk with directory creation 1
REQ-025-073 no BrowserProviderConfig is a frozen dataclass 1
REQ-025-074 no Config contains: name, base_url, login_url, input_selector, submit_selector, response_selector, completion_indicator, code_block_selector, rate_limit_seconds, max_session_minutes, timeout_seconds 1
REQ-025-075 no BROWSER_PROVIDERS dict registers qwen_chat, deepseek_chat, kimi none
REQ-025-076 no get_provider_config(provider) raises ValueError for unrecognised key 1
REQ-025-077 no qwen_chat: rate_limit=5s, max_session=60min, timeout=120s none
REQ-025-078 no deepseek_chat: rate_limit=10s, max_session=30min, timeout=180s none
REQ-025-079 no kimi: rate_limit=8s, max_session=45min, timeout=150s none
REQ-025-080 no extract_file_blocks splits response on ^FILE:\s* (multiline regex) 1
REQ-025-081 no Filename extracted from first line after FILE: marker 1
REQ-025-082 no Fenced code block following filename extracted via state machine 2
REQ-025-083 no Blocks with empty filenames or empty code silently skipped 1
REQ-025-084 no extract_markdown_code_blocks uses DOTALL regex for multi-line blocks 1
REQ-025-085 no Language tag captured in markdown extraction (empty string if absent) 1
REQ-025-086 no Blocks with only whitespace content skipped 1
REQ-025-087 no Package name is orchestrata-drivers, namespace orchestrata.drivers none
REQ-025-088 no __init__.py exports: AsyncCodeDriver, BrowserDriver, BrowserProviderConfig, BROWSER_PROVIDERS, get_driver, extract_file_blocks, extract_markdown_code_blocks none
REQ-025-089 no All public classes and functions carry @traces decorator none
REQ-025-090 no playwright listed as optional dependency under [browser] extra none
REQ-025-091 no ClaudeCodeDriver accepts an optional volk alias and resolves it to a --model value via get_volk_model 1
REQ-025-092 no ClaudeCodeDriver appends the shared team persona via --append-system-prompt when a volk alias is supplied 1
REQ-025-093 no ClaudeCodeDriver emits --output-format json on every invocation and parses the resulting JSON envelope 2
REQ-025-094 no ClaudeCodeDriver emits --resume <last_session_id> on is_fix when a previous session id was captured from the JSON envelope 2
REQ-025-095 no ClaudeCodeDriver emits --settings <path> when ORCHESTRATA_CLAUDE_SETTINGS or auto-generated governance settings are present 1
REQ-025-096 no ClaudeCodeDriver.__init__ auto-generates .claude/orchestrata-settings.json when ORCHESTRATA_CLAUDE_GOVERNANCE=1 and no explicit settings path is set 2
REQ-025-097 no write_governance_settings writes a stable, sorted .claude/orchestrata-settings.json wiring a PreToolUse hook to scripts/claude_governance_gate.py 2
REQ-025-098 no claude_governance_gate reads a JSON payload from stdin and extracts tool_name, tool_input, and session_id none
REQ-025-099 no claude_governance_gate delegates the allow/deny decision to ToolInterceptor.intercept() none
REQ-025-100 no claude_governance_gate emits the Claude Code deny-decision envelope when the interceptor returns BLOCK none
REQ-025-101 no claude_governance_gate fails open (exit 0, allow) on malformed stdin or interceptor construction/call failure none
REQ-025-102 no claude_governance_gate appends one JSONL audit line per decision when ORCHESTRATA_CLAUDE_GATE_LOG is set none

Code that traces this spec

Module Symbols Requirements
orchestrata_ultimate/drivers/aider_driver 5 6
orchestrata_ultimate/drivers/base 2 6
orchestrata_ultimate/drivers/browser_driver 14 22
orchestrata_ultimate/drivers/browser_providers 2 3
orchestrata_ultimate/drivers/claude_api_driver 5 8
orchestrata_ultimate/drivers/claude_code_driver 9 14
orchestrata_ultimate/drivers/claude_settings 2 1
orchestrata_ultimate/drivers/deepseek_coder_driver 1 2
orchestrata_ultimate/drivers/driver_factory 6 12
orchestrata_ultimate/drivers/extraction 3 7
orchestrata_ultimate/drivers/qwen_driver 3 3

Checklists

checklists/constitutional.md

Code Generation Drivers Constitutional Checklist

Security and Access Control
Subprocess Safety
Filesystem Safety
Browser Automation Safety

checklists/requirements.md

The requirement list above comes from this file; 0 of 102 checkbox items are ticked.

checklists/testing.md

Code Generation Drivers Testing Checklist

AsyncCodeDriver Protocol
get_driver Factory
ClaudeCodeDriver
ClaudeAPIDriver
AiderDriver
DeepSeekCoderDriver
QwenDriver
BrowserDriver — Init and Launch
BrowserDriver — Rate Limiting and Session
BrowserDriver — Prompt Construction
BrowserDriver — Recovery
BrowserDriver — Response Processing
BrowserProviderConfig
extraction.py — extract_file_blocks
extraction.py — extract_markdown_code_blocks
Integration Tests

Other tracked files

Full spec text

Verbatim from specs/025-code-generation-drivers/spec.md; headings are pushed down two levels.

SPEC-025: Code Generation Drivers

Metadata


Overview

What

The Code Generation Drivers package (orchestrata-drivers) provides a uniform async interface over multiple external code generation tools and LLM providers. A single Protocol (AsyncCodeDriver) is implemented by seven concrete drivers covering Claude Code CLI, Anthropic API (via Claude Code stdin pipe), Aider CLI, DeepSeek API, Qwen CLI, and three browser-based free-tier LLM web UIs (Qwen Chat, DeepSeek Chat, Kimi). A factory function (get_driver) selects the correct driver from a volk's configured LLM provider. Shared extraction utilities parse FILE: blocks and markdown code blocks from raw LLM output.

Why
How

User Scenarios

US-001: Unified Code Generation Interface

Acceptance Criteria:

US-002: Browser-Based Free-Tier LLM Access

Acceptance Criteria:

US-003: Code Artifact Extraction

Acceptance Criteria:

US-004: Provider Configuration Routing

Acceptance Criteria:

What

The Code Generation Drivers package (orchestrata-drivers) provides a uniform async interface over multiple external code generation tools and LLM providers. A single Protocol (AsyncCodeDriver) is implemented by seven concrete drivers covering Claude Code CLI, Anthropic API (via Claude Code stdin pipe), Aider CLI, DeepSeek API, Qwen CLI, and three browser-based free-tier LLM web UIs (Qwen Chat, DeepSeek Chat, Kimi). A factory function (get_driver) selects the correct driver from a volk's configured LLM provider. Shared extraction utilities parse FILE: blocks and markdown code blocks from raw LLM output.

Why
How

Data Models

AsyncCodeDriverResult
{
  "type": "object",
  "properties": {
    "success": {
      "type": "boolean",
      "description": "True if driver executed without errors"
    },
    "output": {
      "type": "string",
      "description": "Raw output from the driver or error message"
    }
  },
  "required": ["success", "output"]
}
BrowserProviderConfig
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Human-readable provider label"
    },
    "base_url": {
      "type": "string",
      "format": "uri",
      "description": "Chat page URL"
    },
    "login_url": {
      "type": "string",
      "format": "uri",
      "description": "Authentication page URL"
    },
    "input_selector": {
      "type": "string",
      "description": "CSS selector for prompt textarea"
    },
    "submit_selector": {
      "type": "string",
      "description": "CSS selector for send button"
    },
    "response_selector": {
      "type": "string",
      "description": "CSS selector for response container"
    },
    "completion_indicator": {
      "type": "string",
      "description": "CSS selector appearing on generation complete"
    },
    "code_block_selector": {
      "type": "string",
      "description": "CSS selector for code blocks"
    },
    "rate_limit_seconds": {
      "type": "integer",
      "minimum": 1,
      "description": "Minimum seconds between requests"
    },
    "max_session_minutes": {
      "type": "integer",
      "minimum": 1,
      "description": "Max session duration before re-auth"
    },
    "timeout_seconds": {
      "type": "integer",
      "minimum": 10,
      "description": "Per-request timeout"
    }
  },
  "required": ["name", "base_url", "login_url", "input_selector", "submit_selector", "response_selector", "completion_indicator", "code_block_selector", "rate_limit_seconds", "max_session_minutes", "timeout_seconds"]
}
CodeGenerationTask
{
  "type": "object",
  "properties": {
    "task": {
      "type": "string",
      "description": "The full coding prompt to submit"
    },
    "files": {
      "type": ["array", "null"],
      "items": {"type": "string"},
      "description": "Optional list of relative file paths"
    },
    "is_fix": {
      "type": "boolean",
      "description": "True if prompt is a repair/fix invocation"
    }
  },
  "required": ["task"]
}
ExtractedCodeBlock
{
  "type": "object",
  "properties": {
    "filename": {
      "type": ["string", "null"],
      "description": "Filename for FILE: blocks, null for markdown"
    },
    "language": {
      "type": "string",
      "description": "Programming language identifier"
    },
    "content": {
      "type": "string",
      "description": "Extracted code content"
    }
  },
  "required": ["content"]
}

Architecture

Component Diagram
CodeDirector / Junior Volk
        |
        v
  get_driver(volk, workspace)
        |
   [provider config from orchestrata-llm]
        |
        +-- claude / anthropic --> ClaudeAPIDriver --> claude CLI (stdin pipe)
        |                    \--> ClaudeCodeDriver --> claude --print
        +-- deepseek         --> DeepSeekCoderDriver --> DeepSeek HTTP API
        +-- aider            --> AiderDriver --> aider CLI
        +-- qwen / ollama    --> QwenDriver --> qwen CLI
        +-- *_browser        --> BrowserDriver --> Playwright --> LLM web UI
              |
              +-- qwen_browser    --> qwen_chat     (chat.qwen.ai)
              +-- deepseek_browser --> deepseek_chat (chat.deepseek.com)
              +-- kimi_browser    --> kimi           (kimi.moonshot.cn)

AsyncCodeDriver.execute(task, files, is_fix) -> (bool, str)

BrowserDriver._process_response(response)
        |
        +-- extract_file_blocks(response)     -> [(filename, content)]
        +-- extract_markdown_code_blocks(response) -> [(lang, content)]
File Inventory
File LOC Responsibility
base.py ~30 AsyncCodeDriver Protocol definition
driver_factory.py ~120 get_driver factory; provider routing logic
claude_code_driver.py ~120 Claude Code CLI via subprocess (--print mode)
claude_api_driver.py ~200 Claude Code CLI via stdin pipe; workspace scan
aider_driver.py ~120 Aider CLI subprocess driver
deepseek_coder_driver.py ~150 DeepSeek HTTP API driver
qwen_driver.py ~120 Qwen CLI subprocess driver
browser_driver.py ~380 Playwright browser automation driver
browser_providers.py ~110 BrowserProviderConfig dataclass + BROWSER_PROVIDERS registry
extraction.py ~90 FILE: block and markdown code block extraction
__init__.py ~25 Public API re-exports
Total ~2,055

Terminology

Term Definition
AsyncCodeDriver Runtime-checkable Protocol all drivers implement; single method: execute()
Driver A concrete class that wraps a specific external code generation tool or API
ClaudeCodeDriver CLI driver that runs claude --print --dangerously-skip-permissions as a subprocess
ClaudeAPIDriver Claude Code CLI driver using stdin pipe; scans workspace for generated files
AiderDriver CLI driver that runs aider --message --yes-always --no-auto-commits
DeepSeekCoderDriver HTTP API driver calling the DeepSeek code generation endpoint
QwenDriver CLI driver wrapping the Qwen local CLI tool
BrowserDriver Playwright-based driver for free-tier LLM web UIs
BrowserProviderConfig Frozen dataclass with CSS selectors, URLs, rate limits for a browser provider
BROWSER_PROVIDERS Registry dict mapping provider keys to BrowserProviderConfig instances
get_driver Factory function that reads volk provider config and returns the correct driver instance
Provider routing Mapping of provider string → driver class (e.g. claude → ClaudeAPIDriver)
FILE: block Structured output format: `FILE: path/to/file.py\n```lang\ncontent\n````
3-tier recovery Browser session recovery: level 1 = page navigate, level 2 = browser restart
Storage state Playwright JSON state file persisting login cookies for session reuse
Workspace scan Post-generation walk of the workspace directory to enumerate created files

Interfaces

AsyncCodeDriver Protocol
@runtime_checkable
@traces(spec="005", story="US-007", reqs=["REQ-005-US-007-001"])
class AsyncCodeDriver(Protocol):
    async def execute(
        self,
        task: str,
        files: list[str] | None = None,
        is_fix: bool = False,
    ) -> tuple[bool, str]: ...
get_driver Factory
def get_driver(
    volk: str = "J:Junior",
    workspace: Optional[str] = None,
) -> AsyncCodeDriver: ...
Provider Routing Table
Provider string Driver
claude, anthropic ClaudeAPIDriver
deepseek DeepSeekCoderDriver
aider AiderDriver
qwen, ollama QwenDriver
qwen_browser BrowserDriver(provider="qwen_chat")
deepseek_browser BrowserDriver(provider="deepseek_chat")
kimi_browser BrowserDriver(provider="kimi")
(unrecognised) ClaudeAPIDriver (fallback, logged)

Driver Specifications

ClaudeCodeDriver
ClaudeAPIDriver
AiderDriver
DeepSeekCoderDriver
QwenDriver
BrowserDriver
BrowserProviderConfig

Frozen dataclass fields:

Field Type Purpose
name str Human-readable label
base_url str Chat page URL
login_url str Auth page URL
input_selector str CSS selector for prompt textarea
submit_selector str CSS selector for send button
response_selector str CSS selector for response container
completion_indicator str CSS selector appearing on generation complete
code_block_selector str CSS selector for code blocks
rate_limit_seconds int Minimum seconds between requests
max_session_minutes int Max session duration before re-auth
timeout_seconds int Per-request timeout

Registered providers: qwen_chat (5s rate limit, 60min session), deepseek_chat (10s rate limit, 30min session), kimi (8s rate limit, 45min session).

extraction.py

Timeouts

Driver Timeout Rationale
ClaudeCodeDriver 900s Interactive CLI, longer tasks
ClaudeAPIDriver 1200s Agentic mode writes many files
AiderDriver 300s DeepSeek backend, typically 30-60s
DeepSeekCoderDriver Per HTTP client Single API call
QwenDriver 600s Local CLI, variable performance
BrowserDriver (per provider) 120-180s Web UI response latency

Functional Requirements

FR-001: AsyncCodeDriver Protocol

All drivers MUST implement the AsyncCodeDriver Protocol with signature execute(task: str, files: list[str] | None, is_fix: bool) -> tuple[bool, str].

FR-002: Driver Factory Routing

get_driver(volk: str, workspace: str | None) -> AsyncCodeDriver MUST read the provider from orchestrata.llm.config and return the correct driver instance.

FR-003: CLI Binary Detection

CLI drivers (ClaudeCodeDriver, ClaudeAPIDriver, AiderDriver, QwenDriver) MUST locate their binary via shutil.which with known fallback paths.

FR-004: Subprocess Timeout Enforcement

All CLI drivers MUST enforce timeouts using asyncio.wait_for around subprocess execution.

FR-005: Workspace File Scanning

ClaudeAPIDriver MUST scan the workspace post-execution for source files (.py, .toml, .cfg, .ini, .yaml, .yml), excluding .venv, __pycache__, .git, node_modules, .claude, design.

FR-006: DeepSeek API Integration

DeepSeekCoderDriver MUST call the DeepSeek HTTP API with model=deepseek-coder and use DEEPSEEK_API_KEY from environment.

FR-007: Browser Session Persistence

BrowserDriver MUST persist session state to .browser_state/<provider>_state.json and recover sessions across restarts.

FR-008: 3-Tier Browser Recovery

BrowserDriver MUST implement 3-tier recovery: Level 1 = page navigation, Level 2 = browser restart, with max 3 recovery attempts.

FR-009: Rate Limiting

BrowserDriver MUST enforce provider-specific rate_limit_seconds between requests.

FR-010: Code Extraction Utilities

extraction.py MUST provide extract_file_blocks() and extract_markdown_code_blocks() returning list of tuples.

FR-011: Unknown Provider Fallback

get_driver MUST log a warning and fall back to ClaudeAPIDriver for unrecognised providers.

FR-012: Runtime Protocol Checkability

AsyncCodeDriver MUST be decorated with @runtime_checkable for isinstance checks.


Error Conditions

ID Condition Handling
ERR-001 Binary not found Return (False, "<tool> CLI not found")
ERR-002 asyncio.TimeoutError Return (False, "Timed out after Xs")
ERR-003 Non-zero subprocess exit Return (False, collected_output)
ERR-004 No source files after ClaudeAPIDriver Return (False, "No files generated")
ERR-005 Browser init failure Return (False, "Browser init failed: <exc>")
ERR-006 All browser recovery attempts exhausted Return (False, "All recovery attempts exhausted")
ERR-007 No code blocks in browser response Return (False, "No code blocks found in response")
ERR-008 Unknown provider in get_driver Log warning, fall back to ClaudeAPIDriver
ERR-009 Unknown browser provider in get_provider_config Raise ValueError
ERR-010 Missing DeepSeek API key Return (False, error message)
ERR-011 HTTP API connection error Return (False, "API connection failed: <exc>")
ERR-012 Browser session timeout Return (False, "Session expired, max session time reached")
ERR-013 Invalid workspace path Raise ValueError or return (False, "Invalid workspace")
ERR-014 Playwright selector timeout Return (False, "Element selector timeout: <selector>")
ERR-015 File write permission denied Return (False, "Permission denied writing: <filename>")
Environment Variable Purpose Default
ORCHESTRATA_WORKSPACE Default workspace for all drivers /home/mohamed/workspace
DEEPSEEK_API_KEY API key for DeepSeekCoderDriver (required if provider=deepseek)

Non-Functional Requirements

Performance
Scalability
Reliability
Observability
Maintainability

Examples

Example 1: Basic Code Generation
from orchestrata.drivers import get_driver

# Get driver based on volk configuration
driver = get_driver(volk="J:Junior", workspace="/home/mohased/workspace/project")

# Execute code generation task
success, output = await driver.execute(
    task="Create a FastAPI endpoint for user authentication",
    files=["main.py", "auth.py"],
    is_fix=False
)

if success:
    print("Code generated successfully")
    print(output)
Example 2: Fix Existing Files
driver = get_driver(volk="K:CodeDirector")

# Ask for fixes to existing files
success, output = await driver.execute(
    task="Fix the SQL injection vulnerability in this code",
    files=["user_controller.py", "database.py"],
    is_fix=True
)
Example 3: Code Extraction
from orchestrata.drivers.extraction import extract_file_blocks

raw_response = """
FILE: models/user.py
```python
class User:
    def __init__(self, id: int, name: str):
        self.id = id
        self.name = name

"""

Extract code blocks

blocks = extract_file_blocks(raw_response)

Returns: [("models/user.py", "class User:\n def init(self, id: int, name: str):\n self.id = id\n self.name = name\n")]


##### Example 4: Browser Provider Configuration
```python
from orchestrata.drivers.browser_providers import BROWSER_PROVIDERS

# Access browser provider configuration
qwen_config = BROWSER_PROVIDERS["qwen_chat"]
print(f"Rate limit: {qwen_config.rate_limit_seconds}s")
print(f"Session timeout: {qwen_config.max_session_minutes}min")

# Use with BrowserDriver
from orchestrata.drivers import get_driver
driver = get_driver(volk="qwen_browser")

Dependencies

Dependency Version Purpose
orchestrata-core workspace @traces decorator, traceability
orchestrata-llm workspace get_volk_provider for factory routing
playwright >=1.40 (optional) BrowserDriver headless Chromium
Python stdlib asyncio, re, os, shutil, dataclasses, logging All drivers

Security

Governance

Testing

Integration Points

Component Integration Type Description
orchestrata-llm Import Uses get_volk_provider() for factory routing
orchestrata-core Import Uses @traces decorator for traceability
SPEC-020 (Claude Code Harness) Consumer Uses ClaudeCodeDriver, ClaudeAPIDriver
SPEC-027 (Junior Volk) Consumer Uses get_driver for per-file tasks
SPEC-029 (CodeDirector) Consumer Uses get_driver for swarm coordination
SPEC-011 (Provider Manager) Consumer get_volk_provider source
SPEC-028 (LLM Client) Consumer Shares LLM config abstractions
Playwright Runtime Browser automation library (optional)

Success Criteria

Revision History

Version Date Author Changes
1.0.0 2026-04-04 Mohamed Initial specification
1.1.0 2026-04-09 Mohamed Added User Scenarios, Data Models, Functional Requirements (FR-001-012), Error Conditions (ERR-001-015), Non-Functional Requirements, Examples, Security, Governance, Testing, Integration Points, Success Criteria, Revision History

All public classes and functions carry @traces decorator referencing SPEC-005 (Multi-Agent Coordination) user stories:

SPEC-025 formalises the drivers as a standalone specification; traceability decorators will be updated to reference spec="025" in the next implementation pass.


Spec Relationship
SPEC-005 (Multi-Agent Coordination) Origin of driver user stories US-007, US-010
SPEC-020 (Claude Code Harness) Primary consumer of ClaudeCodeDriver and ClaudeAPIDriver
SPEC-027 (Junior Volk) Junior uses get_driver to dispatch per-file tasks
SPEC-029 (CodeDirector Volk) CodeDirector swarm coordinator uses get_driver
SPEC-011 (Provider Manager) Provides get_volk_provider used by the factory
SPEC-028 (LLM Client) Provides LLM config and provider abstractions

Observability

Logging Requirements
  1. Component Logging
    • Log all major operations with appropriate log levels
    • Include correlation IDs for request tracing
    • Log performance metrics for critical operations
    • Log errors with full context for debugging
Metrics Requirements
  1. Performance Metrics
    • Operation duration histograms
    • Request/error rate counters
    • Resource utilization gauges
    • Business metrics relevant to domain
Tracing Requirements
  1. Distributed Tracing
    • Trace propagation across component boundaries
    • Span attributes for domain-specific context
    • Trace sampling based on operational needs
Alerting Requirements
  1. Critical Alerts
    • Error rate spikes
    • Performance degradation
    • Resource exhaustion
    • Business metric anomalies
Dashboard Requirements
  1. Operational Dashboard
    • Real-time system health
    • Performance trends
    • Error analysis
    • Resource monitoring