New Features (2026-06-19) — Resilience Primitives

Reusable resilience primitives — a retry-with-backoff policy and a circuit breaker — plus an executor command that runs an action list through a named breaker. Pure standard library; both primitives take injectable sleep / clock so they are unit-tested deterministically.

(The existing AC_retry flow command already retries an action body; this adds the reusable RetryPolicy callable wrapper and the new CircuitBreaker.)

RetryPolicy

from je_auto_control import RetryPolicy, retry_call

RetryPolicy(max_attempts=5, backoff=0.1, multiplier=2.0).run(flaky_fn)
retry_call(flaky_fn, max_attempts=3)     # convenience

Retries func on the configured exceptions with exponential backoff (backoff * multiplier**n, optionally capped by max_backoff), re-raising the last error when attempts are exhausted.

CircuitBreaker

from je_auto_control import CircuitBreaker, CircuitOpenError

breaker = CircuitBreaker(failure_threshold=5, reset_timeout=30.0)
try:
    breaker.call(call_remote_service)
except CircuitOpenError:
    ...   # short-circuited — the dependency is down

Opens after failure_threshold consecutive failures and short-circuits (raising CircuitOpenError) until reset_timeout elapses, then half-opens for one trial; a success closes it. Stops a retry storm from hammering a downed dependency.

AC_circuit_call / ac_circuit_call run an action list through a named breaker (state shared across calls), returning {state, record}.