- mark Codex bearer/refresh failures as terminal auth-expired states
- sync refreshed session auth back to rotation slots and revive refreshed dead_auth slots
- stop paired arbiter retry loops when Codex accounts are unavailable
- add regression coverage for rotation leases, follow-up suppression, and arbiter closure
- /stop now resets the active paired task to completed so the next
user message routes to the owner instead of the stuck reviewer
- Owner completion with sawOutput=false (e.g. interrupted by /stop)
no longer auto-triggers the reviewer — treated as interrupted
- Clear pendingProgressText when intermediate updates arrive on an
existing progress message, preventing flushPendingProgress from
overwriting latestProgressText with stale buffered content
Replace scattered reason string literals with a centralized type hierarchy:
- AgentTriggerReason: all possible trigger reasons
- ClaudeRotationReason, CodexRotationReason, NoFallbackCooldownReason:
derived subtypes for specific contexts
- AgentErrorClassification, FallbackTriggerResult, CodexRotationTriggerResult:
discriminated unions for compile-time narrowing
Remove dead export isUsageExhausted() (superseded by
isPrimaryNoFallbackCooldownActive). Replace NO_FALLBACK_COOLDOWN_REASONS
Set with isNoFallbackCooldownReason() type guard.
Add tests for agent-error-detection and provider-retry (423 total passing).
Known limitation: 6 `as CodexRotationReason` casts in Codex rotation paths
where streamed trigger reason is AgentTriggerReason but runtime value is
always CodexRotationReason-compatible.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>