--- id: LLM-WP-0002 type: workplan title: llm-connect — Core Extensions (FR-4 BudgetTracker + FR-3 async) domain: custodian status: completed owner: llm-connect created: 2026-04-01 repo: llm-connect planning_priority: high planning_order: 2 state_hub_workstream_id: 448fa379-eb9e-4808-b3fa-0078f1e4eaba --- # LLM-WP-0002 — Core Extensions (FR-4 + FR-3) **status:** completed **owner:** llm-connect **repo:** llm-connect **created:** 2026-04-01 **depends-on:** LLM-WP-0001 (contracts and tests must exist before Core is modified) ## Purpose Implement the two IHF feature requests that touch the Core layer. FR-4 (BudgetTracker) is additive and non-breaking. FR-3 (async) extends the Core ABC with a default executor fallback — non-breaking, overridable per adapter for native async. Origin: IHUB-WP-0012 Phase 11 — Advanced AI Federation (completed 2026-04-01). ## GAAF notes Both changes are Core-layer modifications under GAAF-2026: - FR-4: new primitive (`BudgetTracker`) + new exception (`LLMBudgetExceededError`) added as optional `RunConfig` field — additive, non-breaking. - FR-3: `async_execute_prompt` added to `LLMAdapter` ABC with a default `asyncio.get_event_loop().run_in_executor(None, ...)` fallback so existing adapters remain valid; native async overrides are provided per adapter. Core contract doc (from WP-0001 T05) must be updated after each change. ## Tasks ```task id: T01 title: 'BudgetTracker dataclass: total, spent, remaining(), thread-safe increment' priority: high status: done state_hub_task_id: "ae27c363-339a-4f78-9737-cf872698f6d8" ``` ```task id: T02 title: 'LLMBudgetExceededError(LLMError) in exceptions.py' priority: high status: done state_hub_task_id: "ea6f6ef7-2cb2-48e2-b9c9-f2b84a1a242b" ``` ```task id: T03 title: 'Optional budget_tracker field on RunConfig' priority: high status: done state_hub_task_id: "fe6dbb73-5d04-45e6-aa91-5eff79aae7ee" ``` ```task id: T04 title: 'Enforcement: adapters check/update tracker, raise LLMBudgetExceededError when exceeded' priority: high status: done state_hub_task_id: "8fd21bc2-598e-4449-8c86-eacde760e23f" ``` ```task id: T05 title: 'Update Core contract doc for BudgetTracker and RunConfig changes' priority: medium status: done state_hub_task_id: "e15745f5-9bb7-45d6-a36b-3a345fb0e9f1" ``` ```task id: T06 title: 'Tests: single call, delegation chain, exceeded error, multi-adapter shared tracker' priority: high status: done state_hub_task_id: "5af37ade-3dd0-4ce9-8ead-be9887913bab" ``` ```task id: T07 title: 'Add async_execute_prompt to LLMAdapter ABC with default executor fallback' priority: high status: done state_hub_task_id: "e221e630-658f-4adb-9f00-7b7df7ab8cb4" ``` ```task id: T08 title: 'Native async override in OpenAIAdapter, GeminiAdapter, OpenRouterAdapter' priority: high status: done state_hub_task_id: "a75c2b2a-e4ef-4cbd-9c5f-7e98c8d3d7e8" ``` ```task id: T09 title: 'Native async for ClaudeCodeAdapter via asyncio.create_subprocess_exec' priority: high status: done state_hub_task_id: "1c50889f-28ed-4c6e-a788-1fc7dcc5a2c3" ``` ```task id: T10 title: 'Update Core contract doc for async_execute_prompt' priority: medium status: done state_hub_task_id: "fa4f9e80-ddee-4d05-a239-fe09e633b0cb" ``` ```task id: T11 title: 'Tests: asyncio.gather over N adapters, timeout propagation, budget interaction' priority: high status: done state_hub_task_id: "bca78609-7f7c-4548-8857-a72e4c760dc6" ``` ### FR-4 — BudgetTracker | ID | Title | Priority | Status | |-----|-------|----------|--------| | T01 | `BudgetTracker` dataclass: `total`, `spent`, `remaining()`, thread-safe increment | high | done | | T02 | `LLMBudgetExceededError(LLMError)` in `exceptions.py` | high | done | | T03 | Optional `budget_tracker: BudgetTracker \| None` field on `RunConfig` | high | done | | T04 | Enforcement: each adapter checks/updates tracker around call; raises on exceeded | high | done | | T05 | Update Core contract doc | medium | done | | T06 | Tests: single call, delegation chain (A→B→C shared tracker), exceeded error, multi-adapter | high | done | ### FR-3 — async_execute_prompt | ID | Title | Priority | Status | |-----|-------|----------|--------| | T07 | Add `async_execute_prompt` to `LLMAdapter` ABC with default executor fallback | high | done | | T08 | Native async override in `OpenAIAdapter`, `GeminiAdapter`, `OpenRouterAdapter` | high | done | | T09 | Native async for `ClaudeCodeAdapter` via `asyncio.create_subprocess_exec` | high | done | | T10 | Update Core contract doc | medium | done | | T11 | Tests: `asyncio.gather` over N adapters, timeout propagation, budget interaction | high | done | ## Exit criteria - `BudgetTracker` enforces caps across a delegation chain of 3 adapters in tests - `asyncio.gather` over 4 mock adapters completes without errors - All existing tests still pass (non-breaking validation) - Core contract doc reflects both additions