Circuit breaker preserves forcedOpen on importFromRedis — closes cold-start breaker drift

2026-05-07

routercircuit-breaker

What We Built

importFromRedis parsed {state, ts, forcedOpen} from Redis but the type cast omitted forcedOpen, so createEntry() always set it to false. Result: a cold-starting ECS task imported a force-opened circuit as regular-open, and the next sentinel probe would re-close it. Fix: include forcedOpen in the cast and propagate it to the entry.

Why It Matters

Sibling bug to PR #185 (cross-task pub/sub recovery). PR #185 fixed steady-state propagation; this fixed boot-recovery propagation. Without both, ECS task replacement could silently un-trip a permanent-failure breaker.

How It Works

Five-line fix: extend the parsed-data type to include forcedOpen?: boolean, then entry.forcedOpen = data.forcedOpen ?? false after entry.state = "open". Regression test stubs Redis with {state, ts, forcedOpen: true} and asserts getCircuit(model).forcedOpen === true after import.

Lockstep Checklist

  • [x] No API route changes (middleware/internal — lockstep N/A)
  • [x] No SDK changes
  • [x] No MCP tool changes
  • [x] Regression test included (test-first invariant per /quality-fleet protocol)
  • [x] Linked to /quality-fleet R1 dashboard at .quality/dashboard.md

Provenance

Auto-found by /quality-fleet R1 (2026-05-07) scanner round, fixed in fix-agent batch under "go for all of it" autonomy grant. PR #201 merged to main as commit 94298e3e6. Finding(s) tracked at .quality/findings.jsonl (entries: "a1b2c3d4e5f6"). Production-deployed via ECS task-def revision 732 series.