V3 QA — Scenario 5: LLM Client (Task 6)
==========================================

Test file: experiments/v3/tests/test_llm_client.py
Result: 14/14 PASSED

TokenBucket:
  - Initial tokens full (burst=10, rate=10/min)
  - Acquire consumes token when available
  - Returns wait time when empty

LLMClient Parsing:
  - Valid JSON parsed correctly → buys the right decision
  - Malformed JSON → returns fallback (decision="skip", confidence=0.0)
  - Missing decision field → defaults to "skip"
  - JSON extraction handles code fences, leading text

LLMClient Call (all mocked via respx):
  - Normal 200 → valid response
  - 429 → retry → 200 (exponential backoff)
  - 429 x3 → fallback response
  - 503 → retry → success
  - Timeout → fallback response
  - Rate limiting enforced across calls

EDGE CASE: LLM timeout (0.001s timeout) → falls back to "skip"
EDGE CASE: Malformed JSON ("this is not JSON at all") → falls back to "skip"
EDGE CASE: OLLAMA_API_KEY not set → RuntimeError

VERDICT: PASS
