The threading.Lock only serialized refreshes within one process, so two Strix
processes sharing one ChatGPT login could both spend the single-use refresh
token and leave one with invalid_grant. Add a best-effort cross-process file
lock (flock) around the re-read/refresh/persist, layered over the in-process
lock and degrading to it where flock is unavailable. The re-read inside the
guard means a caller that loses the race adopts the token the winner just
rotated instead of exchanging the dead one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>