Preserve provider retries during Claude background drain - #1623
Conversation
There was a problem hiding this comment.
🚨 SLOP COP 🚨 · review
Plain English summary: Claude can hit a usage limit while a background agent still sends final events. Those events could hide the failed user request and cancel its scheduled retry. This change keeps recovery tied to the latest accepted user turn. It also suppresses most false turns from late Claude events.
I found two issues:
-
P2 — Active and idle events inspect every thread. The retry plugin now calls the recovery SDK on every normal transition. This adds two loopback calls and several synchronous SQLite reads to most turns. The active and idle handlers should inspect only threads that already have a retry entry.
-
P2 — Bridge errors bypass the new suppression rule. The rule covers SDK messages, but the bridge-error envelope uses another path. A failed result followed by a stream error can still create a false, unaccepted turn and duplicate error output. The common Claude error path should honor the same suppression state.
I found no security issue. The retry checks remain scoped to one thread and require the exact accepted request before reuse.
I also checked architecture and duplication. The database helper has no existing equivalent. Its location in @bb/db is correct. I found no stale names or duplicate recovery policy.
Validation passed for the changed paths:
- Claude adapter: 152 tests.
- Server recovery: 15 tests.
- Provider retry plugin: 21 tests.
- Host daemon contract: 50 tests.
- Type checks: all four affected packages.
- GitHub CI: all required checks pass.
I did not run a browser test. This path needs a real Claude subscription limit and has no browser-only route.
Summary
Root cause
The provider-retry plugin initially scheduled the accepted rate-limited failure. While Claude background output drained, the adapter opened a synthetic turn with no client request or accepted input. Its
thread.activeevent removed the scheduled retry, and recovery then inspected the synthetic failed turn and returnedinput-not-accepted.Validation
git diff --checkpassedThe broader server run passed 1666 tests and had one unrelated existing failure in
third-party-marketplaces.test.tsfor a missing SVG content type.