- Add _update_check_lock (threading.Lock) around all reads/writes to
_update_check_cache in check_for_update() and git_pull, preventing
races on concurrent requests
- Validate returncode for git fetch, rev-parse HEAD, and rev-parse
origin/main; raise RuntimeError on failure so errors are caught and
returned as error payloads instead of silently producing stale/empty SHAs
- Set update_available = commits_behind > 0 (was unconditionally True
when local_sha != remote_sha); prevents false positive when local is
ahead of remote
- Add type="button" and aria-label="Dismiss update" to the icon-only
dismiss button
- Restore btn.innerHTML and btn.disabled in both success and error paths
of applyUpdate(); only hide the banner and clear sessionStorage when
data.status === 'success'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a polite, dismissible banner between the header and navigation
tabs that appears when the local repo is behind origin/main. Shows
commit count and a one-click "Update Now" button that triggers the
existing git_pull action.
- New GET /api/v3/system/check-update endpoint (5-min cache, compares
local HEAD vs origin/main SHA)
- Banner auto-checks on page load then every 30 minutes
- Dismiss persists for the browser session via sessionStorage
- Styled for both light and dark themes
- Cache invalidated after successful git_pull so banner hides immediately
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>