🎯 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
🚀 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.
- 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.
🧩 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.
scripts/tests/llm_client.test.mjs:
- Verify fallback to secondary provider does NOT occur when primary returns 401.
- Verify fallback DOES occur when primary returns 503 and exhausts retries.
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.
Out:
- E2E tests requiring real network calls to Anthropic or Groq.
- Performance benchmarks.
🧪 Acceptance criteria
⚙️ 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.
🎯 Goal
Validate that the retry and error classification logic holds under simulated failure conditions — and prevent regressions as resilience features are added.
📍 Context
scripts/tests/anthropic_client.test.mjs,scripts/tests/groq_client.test.mjs,scripts/tests/llm_client.test.mjs,scripts/tests/smoke.test.mjs🚀 Description
The test suite is already comprehensive for happy-path and input validation scenarios. What is missing is targeted failure injection:
groq_client.test.mjscovers 429 retry — good. No equivalent for 5xx.anthropic_client.test.mjshas no retry count verification tests (no check on exact number of fetch calls).llm_client.test.mjsdoes not verify that provider fallback is blocked on permanent 4xx errors.smoke.test.mjshas no scenario for a run that fails transiently and recovers.🧩 Scope
In:
scripts/tests/groq_client.test.mjs: add cases for HTTP 500, 502, 503, 504 — verify each is retried up tomaxAttemptsthen 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.scripts/tests/llm_client.test.mjs:scripts/tests/retry.test.mjs:AbortError) counted as a retryable attempt.Retry-Afterheader 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 networkTypeErrorcurrently marked asretryable: false— should be retryable.Out:
🧪 Acceptance criteria
callLLM, the secondary provider is never called and exactly one fetch call is made.TypeError) occurs incallAnthropic, the retry count increases by 1 and the error is treated as retryable.AbortError) occurs, it is counted as a retryable attempt and the retry count increases by 1.Retry-Afterheader is present, the retry delay matches the header value (using fake timers — no realsetTimeout).callAnthropicis retried and eventually returns the mocked success response (exact call count asserted).maxAttemptstotal calls.callLLMwith a primary provider returning 503 and exhausting retries: secondary provider IS called.callGroqare each retried up tomaxAttemptsthen throw.⚙️ Constraints
node --test scripts/tests/*.test.mjswithout any additional flags.