Fix#1: Don't sleep after the final exhausted retry attempt in
_graph_request(). The sleep on the last iteration was pure overhead —
the loop exits immediately after, so the caller just waited an extra
backoff period for no reason. Guard with attempt < _MAX_RETRIES - 1.
Task 10: Add threading.Lock (_edits_lock) for all compound operations
on active_edits, which is accessed from both the UI thread and
background edit threads:
- __init__: declare self._edits_lock = threading.Lock()
- open_file: snapshot already_editing and at_limit under the lock,
then release before showing blocking UI dialogs
- process_file: wrap initial dict assignment, waiting=True, the
in-check+waiting=False, and in-check+del under the lock
- on_done_editing_clicked: lock the items() snapshot used to build
waiting_files, preventing iteration over a dict being mutated
Add 8 new unit tests (1 for Fix#1 sleep count, 7 for Task 10 lock).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>