Skip to content

[FEATURE] Chaos test scenarios for transient failure recovery #134

Description

@koydas

🎯 Goal

Validate that the retry and error classification logic holds under simulated failure conditions — and prevent regressions as resilience features are added.

📍 Context

  • Repo: autonomous-dev-loop
  • Domain: Robustness validation
  • Component: scripts/tests/anthropic_client.test.mjs, scripts/tests/groq_client.test.mjs, scripts/tests/llm_client.test.mjs, scripts/tests/smoke.test.mjs

🔗 Status (re-checked 2026-10-01 on main @ 4e499fb)

🚀 Description

The test suite is already comprehensive for happy-path and input validation scenarios. What is missing is targeted failure injection:

  • groq_client.test.mjs covers 429 retry — good. No equivalent for 5xx.
  • anthropic_client.test.mjs has no retry count verification tests (no check on exact number of fetch calls).
  • llm_client.test.mjs does not verify that provider fallback is blocked on permanent 4xx errors.
  • No test injects a network-level error (connection reset) to verify it is treated as retryable. (done)
  • No test verifies timeout abort behaviour.
  • smoke.test.mjs has no scenario for a run that fails transiently and recovers.

Dependencies resolved: #109 (error taxonomy) ✅ and #111 (retry utility) ✅ are both merged. scripts/lib/retry.mjs, scripts/lib/error_taxonomy.mjs, and scripts/lib/anthropic_client.mjs (with retryWithBackoff) are all in place.
Open dependency: #162 (per-provider config in the fallback), for the llm_client.test.mjs fallback cases.

🧩 Scope

In:

  • scripts/tests/groq_client.test.mjs: add cases for HTTP 500, 502, 503, 504 — verify each is retried up to maxAttempts then throws.
  • scripts/tests/anthropic_client.test.mjs: add cases for 500/503 retry (exact call count), 401 immediate throw (1 call only). network reset retried (done).
  • scripts/tests/llm_client.test.mjs (after [BUG] callLLM provider fallback sends the primary provider's model, API key and URL to the fallback provider #162):
    • Verify fallback to secondary provider does NOT occur when primary returns 401.
    • Verify fallback DOES occur when primary returns 503 and exhausts retries, and that the secondary is called with its own URL, key and model.
  • scripts/tests/retry.test.mjs:
    • Backoff sequence correctness (~200, ~400, ~800 ms before jitter).
    • Timeout abort (AbortError) counted as a retryable attempt.
    • Retry-After header respected.
  • scripts/tests/smoke.test.mjs: add one scenario — first LLM call returns 503, second succeeds — verify output is correct and attempt counter is 2.
  • scripts/lib/anthropic_client.mjs: fix network TypeError currently marked as retryable: false — should be retryable. (done: fetchErr.retryable = true)

Out:

  • E2E tests requiring real network calls to Anthropic or Groq.
  • Performance benchmarks.

🧪 Acceptance criteria

  • When a 401 error occurs in callLLM, the secondary provider is never called and exactly one fetch call is made.
  • When a network error (TypeError) occurs in callAnthropic, the retry count increases by 1 and the error is treated as retryable. (Covered on main.)
  • When a timeout (AbortError) occurs, it is counted as a retryable attempt and the retry count increases by 1.
  • When Retry-After header is present, the retry delay matches the header value (using fake timers — no real setTimeout).
  • When all retry attempts are exhausted, the final error is thrown without additional fetch calls.
  • A mocked 503 response on callAnthropic is retried and eventually returns the mocked success response (exact call count asserted).
  • A mocked 503 response that persists across all attempts throws after exactly maxAttempts total calls.
  • callLLM with a primary provider returning 503 and exhausting retries: secondary provider IS called, with its own URL, auth header and model. Requires [BUG] callLLM provider fallback sends the primary provider's model, API key and URL to the fallback provider #162.
  • HTTP 500, 502, 503, 504 on callGroq are each retried up to maxAttempts then throw.
  • Smoke: first LLM call returns 503, second succeeds — output is correct and attempt counter is 2.

⚙️ Constraints

  • All tests must be deterministic — no flakiness from timing.
  • No new test dependencies beyond what is already used in the suite.
  • Tests must pass with node --test scripts/tests/*.test.mjs without any additional flags.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-refinementIssue requires clearer acceptance criteria before automation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions