-
fix(x): harden the Gmail rate-limit cooldown after v0.9.1 field reports (#949)
发布于
2026-09-08 13:39:25 +00:00 A throttled user on v0.9.1 still saw a degraded cycle: the promised resume
time kept sliding forward (5:25 → 5:31), waits pinned at exactly 15 minutes
(the fallback cap, not Gmail's word), and each resume re-tripped the limit
with a full maintenance burst. Root causes and fixes:- No-slide rule: a Gmail-named deadline may always extend an active cooldown
(it's Gmail's own word), but the no-deadline fallback can never extend one.
Un-gated callers failing during a lockout used to slide the resume time
indefinitely. - Per-episode strikes: the 1m→15m ladder escalates only when arming from an
expired state. Concurrent callers used to each burn a strike, jumping the
first lockout straight to the 15-minute cap. - Deadline parsing hardened: space-separated timestamps, UTC/GMT/offset
suffixes, missing zone (assumed UTC — Date.parse would read it as local),
and raw string response bodies, plus the classic ISO-with-Z form. - Recovery probe: getUserEmail keeps making its 1-quota-unit getProfile call
during a lockout (at most once a minute, negative-cached) and its success
calls noteGmailSuccess(), ending a stale cooldown the moment Gmail actually
recovers and resetting the ladder. - The hidden 10s hammer: agent_notes' loop (a leftover "(for testing)" 10s
interval) re-called getProfile every tick until one succeeded — during a
fresh-connect lockout, 6 failing calls a minute, each re-arming the
cooldown. It now attempts at most every 15 minutes and never during a
lockout. - Gentle re-entry: new gmailQuotaTight() (active cooldown + 60s grace after
it, ended early by a successful probe) stands down the inbox prune,
classify sweep, and timer backfill, so the first pass back is the lean core
sync instead of the burst that immediately re-earned the limit. - Lingering red "sync failed" after quiet recovery (pre-existing): a
syncDegraded flag emits a one-time "Gmail sync recovered" run on the first
successful pass after any failure, clearing the sidebar state. - Diagnosability: the console warning and the yellow feed notice now record
whether the wait came from a parsed Gmail deadline or the fallback ladder,
with the exact ISO deadline in the notice details — the next field report's
services.jsonl will say which path fired.
Co-authored-by: Claude Fable 5 noreply@anthropic.com
下载附件
- No-slide rule: a Gmail-named deadline may always extend an active cooldown