Skip to content

Fix hidden sidebar PR polling - #4820

Merged
austinywang merged 3 commits into
mainfrom
issue-2746-github-graphql-api-rate-limit-exhausted
May 31, 2026
Merged

austinywang merged 3 commits into
mainfrom
issue-2746-github-graphql-api-rate-limit-exhausted

Conversation

@austinywang

@austinywang austinywang commented May 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • gate workspace PR polling on sidebar.showPullRequests as well as sidebar.watchGitStatus
  • clear PR metadata/timers when PR rows are hidden while preserving branch metadata
  • pass CMUX_NO_PR_WATCH into shell startup and make legacy bash/zsh PR probes honor it

Fixes #2746.

Regression structure

  • Commit 1 adds failing coverage for hidden sidebar PR polling and legacy shell gh pr view probes.
  • Commit 2 applies the fix.

Testing

  • Not run locally per workspace policy and task instructions. CI should run the regression coverage.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.


Note

Low Risk
Behavioral change is scoped to sidebar PR visibility and shell metadata; branch/git watch paths stay separate, with targeted regression tests.

Overview
PR polling and shell-side gh pr probing now require both sidebar.watchGitStatus and sidebar.showPullRequests, instead of treating git watch alone as enough to drive PR work.

When PR rows are hidden, the app stops timers and clears PR badges while keeping branch metadata. TabManager reacts to showPullRequests toggles separately from disabling all git watch, and terminal report_pr / report_pr_action paths use the new gate. Startup sets CMUX_NO_PR_WATCH (alongside existing git watch env), and bash/zsh integrations skip PR poll loops, command hints, and legacy gh pr view probes when it is set.

Regression tests cover hidden-sidebar polling, settings toggles, env wiring, and no-gh when PR watch is off.

Reviewed by Cursor Bugbot for commit ca60fc8. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Stop polling for pull requests when the PR section is hidden in the sidebar. Re‑enabling PRs resumes polling from preserved branch data. Fixes #2746.

  • Bug Fixes
    • Gate PR polling on both sidebar.watchGitStatus and sidebar.showPullRequests.
    • When hidden, clear PR metadata and timers; keep branch metadata and don’t arm polling from branch reports.
    • Set CMUX_NO_PR_WATCH in startup env; bash/zsh integrations skip legacy gh pr probes and PR poll loops when set.
    • Add regression tests for hidden PR polling, shell probe behavior, and the re‑enable flow.

Written for commit ca60fc8. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features

    • Pull request watching is now independently configurable from git status monitoring.
    • Added support for disabling PR watching in shell integrations via environment variable.
  • Bug Fixes

    • Pull request metadata is now properly cleared when PR watching is disabled.
  • Tests

    • Added tests to verify PR watching can be disabled independently and metadata is correctly cleared.

Review Change Stack

@vercel

vercel Bot commented May 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 26, 2026 8:39pm
cmux-staging Building Building Preview, Comment May 26, 2026 8:39pm

@coderabbitai

coderabbitai Bot commented May 26, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR decouples pull-request polling from git-status watching by adding a new sidebarPullRequestPollingEnabled setting and CMUX_NO_PR_WATCH environment variable. Shell integration guards, startup environment setup, and the application's PR refresh pipeline now respect the new independent PR-polling flag, with PR-specific metadata clearing to ensure state is reset when PR display is disabled.

Changes

PR Watching Disable Feature (showPullRequests/CMUX_NO_PR_WATCH)

Layer / File(s) Summary
Shell Integration PR Watch Guards
Resources/shell-integration/cmux-bash-integration.bash, Resources/shell-integration/cmux-zsh-integration.zsh, cmuxTests/GhosttyConfigTests.swift
Bash and Zsh shell integration add early-return guards in _cmux_emit_pr_command_hint, _cmux_report_pr_for_path, and _cmux_start_pr_poll_loop to suppress PR probing and polling when CMUX_NO_PR_WATCH=1. Tests verify the legacy gh probe is skipped in both shells.
Settings Helper & Startup Environment
Sources/CmuxSettingsJSONPathSupport.swift, Sources/TerminalStartupEnvironment.swift, Sources/GhosttyTerminalView.swift, cmuxTests/GhosttyTerminalStartupEnvironmentTests.swift
Add pullRequestPollingEnabled() helper combining git and PR settings. Update applyManagedGitWatchEnvironment to accept showPullRequestsEnabled parameter and set CMUX_NO_PR_WATCH accordingly. Terminal view passes the parameter at initialization. Test verifies environment variable is set correctly.
Application PR Polling Decoupling & State Management
Sources/TabManager.swift, Sources/TerminalController.swift, Sources/Workspace.swift, cmuxTests/WorkspacePullRequestSidebarTests.swift
TabManager decouples PR polling from git-watch with sidebarPullRequestPollingEnabled state and consolidated sidebarMetadataSettingsDidChange() handler. PR refresh pipeline guards on the new setting and clears PR-specific metadata when disabled. TerminalController guards PR handling paths. Workspace centralizes PR clearing via clearSidebarPullRequestMetadata(). Tests validate branch metadata persists while PR state is cleared independently.

Sequence Diagrams

sequenceDiagram
  participant Shell as Shell Integration
  participant ENV as Environment<br/>(CMUX_NO_PR_WATCH)
  participant GH as gh pr CLI
  participant Hint as PR Hint Handler
  participant Poll as PR Poll Loop
  
  Shell->>ENV: Check CMUX_NO_PR_WATCH
  
  alt CMUX_NO_PR_WATCH=1
    Shell->>Hint: _cmux_emit_pr_command_hint returns early
    Shell->>Shell: _cmux_report_pr_for_path clears cache, returns
    Shell->>Poll: _cmux_start_pr_poll_loop stops loop, returns
  else CMUX_NO_PR_WATCH not set
    Shell->>GH: Execute gh pr list/checks
    Shell->>Hint: Send report_pr_action
    Shell->>Poll: Start background polling
  end
Loading
sequenceDiagram
  participant TabMgr as TabManager
  participant State as sidebarPullRequestPollingEnabled
  participant Handlers as Settings Change Handlers
  participant Refresh as PR Refresh Pipeline
  participant Terminal as TerminalController
  participant WS as Workspace
  
  TabMgr->>State: Track lastSidebarPullRequestPollingEnabled
  TabMgr->>Handlers: sidebarMetadataSettingsDidChange()
  
  Handlers->>Handlers: Check git-watch vs PR-polling separately
  
  alt PR Polling Disabled
    Handlers->>Refresh: sidebarPullRequestPollingSettingsDidChange()
    Refresh->>Refresh: Cancel pending refreshes
    Refresh->>WS: clearAllWorkspaceSidebarPullRequestMetadata()
  else PR Polling Enabled
    Handlers->>Refresh: Schedule/start PR refresh
  end
  
  Refresh->>Refresh: Guard on sidebarPullRequestPollingEnabled
  Refresh->>Refresh: Clear PR metadata if disabled
  
  Terminal->>Terminal: Guard PR paths on pullRequestPollingEnabled()
  Terminal->>WS: Clear PR panel on guard failure
  
  WS->>WS: clearSidebarPullRequestMetadata() separate from git clearing
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • manaflow-ai/cmux#2797: Modifies sidebar disable behavior to clear or short-circuit pull-request sidebar state/refresh logic in the same core places (Workspace PR metadata clearing and TabManager PR polling/scheduling paths), directly connected at the PR-panel state level.

Poem

🐰 A rabbit hops through the GitHub trees,
watching pull requests with PR expertise,
but when showPullRequests turns false,
the polling halts without any pulse,
rate limits safe, the rabbit's at ease! 🌿✨


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Auxiliary Window Close Shortcuts ❌ Error Two new NSWindows with cmux.* identifiers are created but not registered in cmuxAuxiliaryWindowIdentifiers: cmux.bootstrap and cmux.browserBackgroundPreload. Register cmux.bootstrap and cmux.browserBackgroundPreload in the cmuxAuxiliaryWindowIdentifiers set in Sources/cmuxApp.swift to ensure Cmd+W close shortcuts work correctly for these auxiliary windows.
Docstring Coverage ⚠️ Warning Docstring coverage is 1.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (15 passed)
Check name Status Explanation
Linked Issues check ✅ Passed All primary objectives from issue #2746 are addressed: PR polling is now gated on both watchGitStatus and showPullRequests [#2746], PR metadata is cleared when hidden while branch metadata is preserved [#2746], CMUX_NO_PR_WATCH is passed to shell startup [#2746], and legacy bash/zsh probes honor this flag [#2746].
Out of Scope Changes check ✅ Passed All code changes directly support the stated objectives: gating PR polling, clearing PR metadata, implementing CMUX_NO_PR_WATCH environment variable, and adding comprehensive regression tests align with fixing the hidden sidebar PR polling issue.
Cmux Swift Actor Isolation ✅ Passed TabManager and Workspace remain @MainActor-annotated; no mutable shared state exposed to background contexts; new pure helper functions; no shared Sendable types without isolation introduced.
Cmux Swift Blocking Runtime ✅ Passed PR uses non-blocking timers, async/await, and async dispatch only. No semaphores, locks, or blocking waits in production code. Task.sleep only in test scaffolding.
Cmux No Hacky Sleeps ✅ Passed PR adds only early-return guards for CMUX_NO_PR_WATCH=1, not new sleep/timer code. Existing sleeps in PR polling are now prevented from executing via guards.
Cmux Swift Concurrency ✅ Passed PR adds guards on existing Task/DispatchSource usage to control PR polling; introduces no new background queues, Combine patterns, completion handlers, or unmanaged fire-and-forget Tasks.
Cmux Swift @Concurrent ✅ Passed All added Swift code is synchronous state management. No async/await, @concurrent, or network operations. Proper MainActor isolation. No concurrent annotation violations.
Cmux Swift File And Package Boundaries ✅ Passed All Swift file changes comply: new files under 400 lines with single responsibility, <250 lines added to existing oversized files, focused bug fix touching app-target code incidentally.
Cmux Swift Logging ✅ Passed PR contains no new print, debugPrint, dump, or NSLog calls in app/runtime code; modified files add PR polling logic without violating logging standards.
Cmux User-Facing Error Privacy ✅ Passed No user-facing errors added; environment variables only set internally in TerminalStartupEnvironment.swift; no vendor names, credentials, or sensitive info exposed.
Cmux Full Internationalization ✅ Passed PR adds only logic/infrastructure for PR polling; no new user-facing text added; environment variables are literal configuration tokens.
Cmux Swiftui State Layout ✅ Passed PR adds private state variables for PR polling in TabManager using private var (not @Published/@observable), with mutations in explicit methods. No SwiftUI layout violations detected.
Cmux Architecture Rethink ✅ Passed Gating PR polling via single computed property from UserDefaults, using guard patterns with no timing repairs, no duplicate state owners, clear invariant naming in tests.
Title check ✅ Passed The title 'Fix hidden sidebar PR polling' clearly and concisely summarizes the main change—preventing PR polling when the sidebar PR section is hidden, which directly addresses the core issue described in the PR objectives.
Description check ✅ Passed The PR description provides a clear summary of changes, testing approach, and references the fixed issue #2746. It includes commit structure and testing notes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-2746-github-graphql-api-rate-limit-exhausted

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented May 26, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR gates workspace PR polling on sidebar.showPullRequests in addition to sidebar.watchGitStatus, fixing a bug where hiding the PR sidebar section did not stop GitHub API calls. The new pullRequestPollingEnabled computed property (watchGitStatus && showPullRequests) becomes the single source of truth for all PR work — timers, refresh tasks, shell report_pr/report_pr_action command processing, and the CMUX_NO_PR_WATCH startup env var.

  • Adds clearSidebarPullRequestMetadata() to Workspace that removes only PR state while preserving panelGitBranches, and plumbs sidebarPullRequestPollingSettingsDidChange() in TabManager to call it on toggle, then rearming polling from preserved branch data on re-enable.
  • Propagates CMUX_NO_PR_WATCH=1 into new terminal startup environments and adds early-exit guards in bash/zsh for _cmux_report_pr_for_path, _cmux_start_pr_poll_loop, and _cmux_emit_pr_command_hint.
  • Adds regression tests for the hidden-sidebar polling path, the toggle-off/toggle-on lifecycle, and the shell probe suppression.

Confidence Score: 5/5

Safe to merge — the change is a targeted gating of PR work behind the existing showPullRequests preference, with no modifications to the git-watch or branch-metadata paths.

The fix correctly propagates the new pullRequestPollingEnabled flag through every PR entrypoint: the poll timer, the refresh task, the two TerminalController shell commands, applyGitProbeSnapshot, and the startup environment. Branch metadata is preserved across the toggle. The re-enable path is exercised by the second new test. No data loss, no timing hazards, and no actor-isolation issues introduced.

No files require special attention.

Important Files Changed

Filename Overview
Sources/TabManager.swift Core fix — introduces sidebarPullRequestPollingEnabled, sidebarPullRequestPollingSettingsDidChange, clearAllWorkspaceSidebarPullRequestMetadata, and clearWorkspacePullRequestMetadata(for:); guards all PR scheduling and apply paths on the new flag. Consistent with the existing git-metadata watching pattern.
Sources/Workspace.swift Extracts clearSidebarPullRequestMetadata() from clearSidebarGitMetadata(), preserving branch metadata when only PR visibility is toggled off.
Sources/TerminalController.swift Switches report_pr and report_pr_action shell command guards from watchGitStatusValue to pullRequestPollingEnabled; clears stale PR on both paths when disabled.
Sources/TerminalStartupEnvironment.swift Adds showPullRequestsEnabled parameter with a safe default of true; sets CMUX_NO_PR_WATCH correctly as the conjunction of both flags.
Sources/GhosttyTerminalView.swift Passes showPullRequestsEnabled from live UserDefaults to applyManagedGitWatchEnvironment; correct and complete update.
Resources/shell-integration/cmux-bash-integration.bash Adds CMUX_NO_PR_WATCH guards to _cmux_emit_pr_command_hint, _cmux_report_pr_for_path, and _cmux_start_pr_poll_loop; zsh integration receives identical changes.
cmuxTests/WorkspacePullRequestSidebarTests.swift Two new tests cover: (1) branch reports don't arm PR polling when showPullRequests=false, and (2) toggle-off clears PR state while preserving branches, toggle-on rearmed from preserved branches. Both paths exercised.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[UserDefaults change] --> B[sidebarMetadataSettingsDidChange]
    B --> C[sidebarGitMetadataWatchSettingsDidChange]
    B --> D[sidebarPullRequestPollingSettingsDidChange]

    D --> E{pullRequestPollingEnabled\nwatchGitStatus && showPullRequests}
    E -- false --> F[resetWorkspacePullRequestRefreshState\ncancel task + clear all tracking dicts]
    F --> G[clearAllWorkspaceSidebarPullRequestMetadata\npanelPullRequests + pullRequest cleared\npanelGitBranches preserved]
    E -- true --> H[refreshTrackedWorkspacePullRequestsIfNeeded\nrearmed from panelGitBranches]

    subgraph Terminal Startup
        I[applyManagedGitWatchEnvironment\nwatchGitStatus + showPullRequests] --> J[CMUX_NO_GIT_WATCH]
        I --> K[CMUX_NO_PR_WATCH]
    end

    subgraph Shell Integration
        K -- ==1 --> L[_cmux_start_pr_poll_loop\nstop loop and return]
        K -- ==1 --> M[_cmux_report_pr_for_path\nclear cache and return]
        K -- ==1 --> N[_cmux_emit_pr_command_hint\nreturn early]
    end

    subgraph TerminalController
        O[report_pr / report_pr_action] --> P{pullRequestPollingEnabled}
        P -- false --> Q[clearPanelPullRequest]
        P -- true --> R[update / schedule PR refresh]
    end
Loading

Reviews (2): Last reviewed commit: "test: cover PR polling reenable" | Re-trigger Greptile

Comment thread cmuxTests/WorkspacePullRequestSidebarTests.swift
Comment thread Sources/TabManager.swift
@austinywang
austinywang merged commit 22855fe into main May 31, 2026
23 checks passed

This branch was successfully deployed

1 active deployment
Preview – cmux — ca60fc8d Deployed May 26, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitHub GraphQL API rate limit exhausted by background gh pr checks/list polling despite showPullRequests: false

1 participant