Skip to content

cmux NEXT: connect the GitHub App from Settings Accounts - #26770

Merged
teamleaderleo merged 26 commits into
feat-cmux-nextfrom
lane/github-connect-settings
Nov 2, 2026
Merged

teamleaderleo merged 26 commits into
feat-cmux-nextfrom
lane/github-connect-settings

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Settings → Accounts gains one Connect GitHub action backed by the existing GitHub App connection API. A user chooses repositories and permissions in GitHub, then returns to Settings to see the connection, its granted permissions, and Disconnect. Pending browser authorization stays pending until the API confirms completion.

"one 'Connect GitHub' in Settings and onboarding"
"No gh auth login anywhere in the UI."

Depends on #26795 for typed result effects. The dashboard callback preserves the originating team through completion in merged #26804 (04f80b97).

Settings and onboarding share accounts.githubConnect (cmux accounts github-connect), which reports connected, pending, needs-action, or failed with localized recovery text. The Setup Guide button is carried by #26780. The Inbox preference is relabeled GitHub Inbox because it controls notifications, with its behavior and default preserved.

The native account/team scope binds every request and discards responses after switching accounts. Existing owner-session HTTPS transport is used; no credential-relay permission or backend behavior changes. Only a connection's creator sees an enabled Disconnect action. Connect retries retain the same idempotency key after a lost response; cached browser URLs expire with their signed authorization state, and a failed request returns a failed CLI action; repeated setup does not create another active connection. Showcase and isolated Accounts fixtures disable the live transport. Browser completion uses the existing dashboard callback; this does not claim access from other machines.

Validation at b497fafd2aa0df3e8f129a478eb9fd0793a14fcb: static pre-push checks passed. Fleet job 0a87afee31dec79469dc2d73 compiled the test targets and passed GitHubConnectionsTests (16 tests), ActionSurfaceParityTests (two skips), and ActionEffectTests. The same new regression cases on pre-fix b09afc6004cb715653a298dc21874cca00ef13c0 failed in fleet job 38662545ac0188fa553ba756: the policy retry reused its refused key, and the restored pending connection allowed two duplicate attempts. No test crash or incomplete run is counted as a pass.

Definitive connection refusals now discard their mutation key; a lost response or indeterminate transport/server failure keeps it for safe retry. A pending flow restored without its browser URL disables Connect; locally cached flows remain resumable, including renewal after state expiry. The GitHub App connection still uses the existing integration API; the daemon lease is not managed by Settings.

The current review repair at e004e898c1ebc879332acf9dbf483fe2d2670e75 isolates retry-key changes to the current account generation and refuses personal-team fallback under a managed-team restriction. Regression tests exercise an obsolete refusal arriving while a newer attempt is in flight, and missing/wrong managed teams making zero API calls. Exact-head focused verification and independent review are in progress.

Earlier focused web run 40652260308 passed types and rendered the fixture treatments. Its image-log transport lost bytes, so those renders are not claimed as retained screenshots; the fleet captures below replace them.

Size: this remains one Accounts connection state machine, its actions, localized copy, and regression/gallery coverage (about 880 changed lines). Splitting the state from its UI and behavior tests would leave an incomplete connection flow.

No new timer or observer is introduced; the existing Settings subscription and focus lifecycle refresh the connection state. HTTP requests use the existing 15-second bounded transport.

Design: existing Accounts rows and glass, secondary descriptions, and quiet actions. Three gallery treatments (balanced, compact, inline) plus pending, empty, and disconnect-confirmation states use synthetic data. Reference: Claude's Settings session-workflow rows; no private reference screenshot is published.

Captures

Settings > Accounts opened with accounts.show, signed out, on a fleet capture mini. Before is the merge base, after is the head build: the new GitHub group appears under the cmux account with Connect GitHub disabled until sign-in.

Before (9f6a7512cc7c, see marker below for the exact commit):

Capture steps-c31ce0cf51 at 940e57433514 (fleet build, capture mini, text checked for private data)

Light Dark
light dark

After:

Capture steps-c31ce0cf51 at c93b079685ba (fleet build, capture mini, text checked for private data)

Light Dark
light dark

Viewed after image: yes
Visual verdict: The new GitHub group sits under the cmux account in Settings Accounts with the same card, spacing and button style as its neighbours in light and dark, and Connect GitHub reads as disabled until sign-in.

Verification

  • At 6a1f1cb5 (fleet): GitHubConnectionsTests (with the new lost-connect pending regression), ActionEffectTests, ActionSurfaceParityTests pass.
  • The head 6976e112 merges feat-cmux-next into f218b875, resolving one conflict in ActionSurfaceCatalog+MenuExemptions.swift by keeping both accounts.githubConnect and settings.customizeMenus. CI at this head and the base-red classifier decide its reds.
  • Review at 6976e112 (Sol): no blocking finding. Its two P2s land as follow-ups under the 2026-10-30 severity rule: GitHub connect: reopen a cached authorization URL when the refresh fails #28716 (reopen a cached authorization URL when the refresh fails) and GitHub connect: discard a response after an A→B→A account switch #28717 (discard a response after an A→B→A account switch).

Agent session: agent session

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 5468259: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr26770 -f ref=lane/github-connect-settings -f platform=macos -f backend_mode=local

Gallery before/after for 5468259: 16 states rendered, 14 images differ, 2995 more touched states not rendered. Images are in the run's artifact, not on this public PR; the independent review of this head reads them on its own, so the PR needs no hand-made screenshots of these states.

gh run download 41505794507 -R manaflow-ai/cmux -n gallery-advisory-26770-54682590a51f4b8886c724c7c863687039f8d03b (then read gallery-review.json)

States
State Theme Status Diff Picked by
pages.settings/github-connect-balanced Apple System Colors Light new 0% own AccountsSection.tsx
pages.settings/github-connect-balanced Apple System Colors new 0% own AccountsSection.tsx
pages.settings/github-connect-compact Apple System Colors Light new 0% own AccountsSection.tsx
pages.settings/github-connect-compact Apple System Colors new 0% own AccountsSection.tsx
pages.settings/github-connect-inline Apple System Colors Light new 0% own AccountsSection.tsx
pages.settings/github-connect-inline Apple System Colors new 0% own AccountsSection.tsx
pages.settings/github-connect-comparison Apple System Colors Light new 0% own AccountsSection.tsx
pages.settings/github-connect-comparison Apple System Colors new 0% own AccountsSection.tsx
pages.settings/github-connect-empty Apple System Colors Light new 0% own AccountsSection.tsx
pages.settings/github-connect-empty Apple System Colors new 0% own AccountsSection.tsx
pages.settings/github-connect-pending Apple System Colors Light new 0% own AccountsSection.tsx
pages.settings/github-connect-pending Apple System Colors new 0% own AccountsSection.tsx
pages.settings/github-connect-confirm Apple System Colors Light new 0% own AccountsSection.tsx
pages.settings/github-connect-confirm Apple System Colors new 0% own AccountsSection.tsx
pages.settings/model-picker-placement-inherited Apple System Colors Light unchanged 0% own AccountsSection.tsx
pages.settings/model-picker-placement-inherited Apple System Colors unchanged 0% own AccountsSection.tsx
pages.settings-initials/profiles Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-initials/profiles Apple System Colors unchanged 0% imports ops.ts (1 hops)
pages.settings-initials/machines Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-initials/machines Apple System Colors unchanged 0% imports ops.ts (1 hops)
pages.settings-menus/generated Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-menus/generated Apple System Colors unchanged 0% imports ops.ts (1 hops)
pages.settings-menus/customized Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-menus/customized Apple System Colors unchanged 0% imports ops.ts (1 hops)
pages.settings-menus/terminal Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-menus/terminal Apple System Colors unchanged 0% imports ops.ts (1 hops)
pages.settings-server/current Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-server/current Apple System Colors unchanged 0% imports ops.ts (1 hops)
pages.settings-server/restart-recommended Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-server/restart-recommended Apple System Colors unchanged 0% imports ops.ts (1 hops)
pages.settings-server/none Apple System Colors Light unchanged 0% imports ops.ts (1 hops)
pages.settings-server/none Apple System Colors unchanged 0% imports ops.ts (1 hops)

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

Passes: CI passes on 54682590a5.

CI passes on 54682590a5 (run 41505794799 attempt 1).

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

web and size checks: green

Default changes

This pull request changes 3 defaults at 54682590a51f (what everyone gets without configuring anything):

  • tunable-source.CmuxNextApp/Handlers/AccountsHandlers.swift:bind: "1d726c4a502f628fa8e9b9eb05f268d98d0a549389b4ffd5d4926b550385a650" -> "df9b051651bc930469164629a242646c8e4e2e7c08818b993f65171175983617"
  • tunable-source.CmuxNextApp/Handlers/AccountsHandlers.swift:githubConnectResult: (none) -> "eae0623357f1aeda6d1253abe95ef06f3663671088418ae8138d82cccb54c9d8"
  • tunable-source.CmuxNextSettings/Schema/SettingsSchema+Feed.generated.swift:descriptors: "70aaf7541ea894edf03c43e350d86e18c13434cc1922d4cb9256915bb354988f" -> "c1434b258a2d40e4bcfb95b56872c7bb8573782098103fcf548b8909fab10626"

Signed off on this commit by review (next-review patch-id; carried).

Merge receipt: merged as 8219b5769870 with these defaults changed, signed off by review (next-review patch-id; carried).

Regenerate the snapshot with python3 scripts/ci/defaults_guard.py snapshot.

Shipped in:

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 28, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Found 2 test failures on Blacksmith runners:

Failures

Test View Logs
test_every_compile_job_names_its_warm_sources (main.ThisTree.test_every_compile_job
_names_its_warm_sources)/
test_every_compile_job_names_its_warm_sources (main.ThisTree.test_every_compile_job
_names_its_warm_sources)
View Logs
the short nightly decide gate must use the pooled Linux route with a Blacksmith fallbac
k/
the short nightly decide gate must use the pooled Linux route with a Blacksmith fallbac
k
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-hin4ou created for this PR by the cmux coordinator.

@teamleaderleo
teamleaderleo force-pushed the lane/github-connect-settings branch from e138320 to 67e4654 Compare October 28, 2026 07:55
…-connect-settings

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextActions/ActionSurfaceCatalog+Exemptions.swift
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high, review-router): SHIP at 097e4f7

No new P1/P2. The regenerated exports, counts, settings schema, MDM files and fingerprints match their sources. git diff --stat 6976e112..097e4f73 is exactly those 7 generated files. Follow-ups #28716 and #28717 stand under the 2026-10-30 severity rule.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high, review-router): SHIP at d6bea6c

No P1/P2. The P1 reported at f63c16f (ActionEffect.applied(result:) missing) was wrong: this PR adds it at ActionEffect.swift:40, and fleet step 82755dc6 compiled CmuxNextAppTests at f63c16f and passed GitHubConnectionsTests (19), ActionEffectTests (8) and ActionSurfaceParityTests (12). That review's P2 is filed as #29128 under the 2026-10-30 severity rule, beside #28716 and #28717. One nit: the comment at GitHubConnections.swift:112 says refusals replay under their mutation key, but the code clears it.

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextActions/ActionSurfaceCatalog+Exemptions.swift
# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextActions/ActionSurfaceCatalog+Exemptions.swift
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high fast, review-router): BLOCK at 37196f6

  • P2: A pending authorization can't be resumed when the refresh request fails. connect() always runs githubRefresh and returns on error, so during a transient list failure it never opens the cached URL or retries the retained idempotency key. GitHubConnections.swift:57 (diff line)
  • P2: Switching accounts can expose stale GitHub state. currentConnections reuses cached rows whenever the scope returns to an earlier value, and the response guard accepts late results after an A→B→A switch because the generation is unchanged. GitHubConnections.swift:40, :97 (diff lines)

VERDICT: BLOCK

Lander note: these are the findings already filed as #28716 and #28717.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: no activity for 18 h, and no lane holds a lease on it. The orphan sweep could not merge feat-cmux-next in: conflicts in plans/cmux-next/action-surfaces.json, plans/cmux-next/actions.md, schemas/settings/settings-schema.json. Listed for a lane to resolve.

Generated exports (action surfaces, settings schema, MDM docs) are taken from
the base; the PR autofix regenerates the ones this PR owns.
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, next-review): BLOCK at c826899

BLOCK at c826899

Visual verdict: The new GitHub rows have large blank vertical gaps in both themes, pushing existing provider controls off-screen in the exact-head gallery.

  1. [P1] [blocking] webviews/src/pages/settings/components/GitHubAccountsCard.tsx:15 — Both labels sit directly inside column-flex .row elements. Below 640px, refined.css:271 gives them flex-basis: 10rem, which becomes vertical space. Gallery images 01–14 show the resulting oversized cards. Wrap both labels in .row-main, matching existing Accounts rows.

  2. [P2] [follow-up] Packages/macOS/CmuxNext/Sources/CmuxNextAccounts/GitHubConnections.swift:63 — Connect silently drops the request when a same-scope refresh is already running. Both calls from connect() return immediately, so CLI/palette reports pending without opening authorization or scheduling a connection. Await the running refresh before continuing Connect.

Follow-ups:

  • Finding 2: preserve Connect requests that overlap a Settings refresh.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, sweep, via the review router; full diff from merge base 80d716d to this head): SHIP at c826899

[P2] [follow-up] Packages/macOS/CmuxNext/Sources/CmuxNextAccounts/GitHubConnections.swift:40 - connection data is retained under a single connections array; switching from scope A to B and back to A exposes A’s stale rows as ready without a fresh integration.list, allowing outdated connect/disconnect decisions - invalidate cached state on scope changes or refresh before reusing it.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (next-review patch-id; carried): SHIP at 5468259

The independent SHIP at c826899 carries to this head: the PR's own change (git diff $(git merge-base feat-cmux-next HEAD) HEAD) has the same git patch-id --verbatim (1bfa03723ab75fa7) at both heads, and no merge between them was resolved by hand. Nothing new to review. A newer BLOCK, or any change to the PR's own diff, ends the carry.

@lawrencecchen

Copy link
Copy Markdown
Contributor

Swift-logic note (REWRITE R-SWIFT-MIRRORS): this PR added GitHubConnections to CmuxNextAccounts (+260 counted lines). It keeps a Swift copy of the cloud owner's connection list per account and team, and the connect flow rules. That state belongs to the daemon's sync actor, which owns the cloud client and the current account and team (layer-ownership.md V-12; wave W7, target 11-20).

Why this matters: the tip's swift_logic_lines report (scripts/cmux-next/swift-logic-lines.py) has been red since 2026-11-02, and this PR is one of the rises. The project rule is that Rust owns state, lists and rules, and Swift is the platform shell (plans/cmux-next/layer-ownership.md; the cmux-next-feature skill: "Move as much as possible into Rust"). For new code of this kind, please put the rule in Rust (a crate the app links through cmux-app-ffi, or the daemon) and keep only the platform call in Swift. If a part truly must stay in Swift, add its row to plans/cmux-next/swift-logic-classes.tsv in the same PR, with the reason.

Nothing to change in this merged PR. REWRITE R-SWIFT-MIRRORS tracks the move (design: https://cmux-orchestrator-1.tail137216.ts.net/resize-videos/rewrites/R-SWIFT-MIRRORS/DESIGN.md, section 11).

@lawrencecchen

Copy link
Copy Markdown
Contributor

Swift logic follow-up (tip watcher swift-logic row, STATUS 13027 "SWIFT LOGIC CULPRITS"; lead order).

This PR raised swift_logic_lines by +211 at its merge commit 8219b57: scripts/cmux-next/swift-logic-lines.py before and after the merge, with the same table (the tip's, c6be943). The largest declarations of the rise:

  • class GitHubConnections in Packages/macOS/CmuxNext/Sources/CmuxNextAccounts/GitHubConnections.swift: +146 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)
  • extension GitHubConnections in Packages/macOS/CmuxNext/Sources/CmuxNextApp/Accounts/AccountsService.swift: +35 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)
  • extension GitHubConnections in Packages/macOS/CmuxNext/Sources/CmuxNextAccounts/GitHubConnections+Page.swift: +25 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)
  • enum AccountActionCatalog in Packages/macOS/CmuxNext/Sources/CmuxNextActions/Catalog/AccountActionCatalog.swift: +5 lines counted as Swift logic (its row counts it as logic)

plans/cmux-next/layer-ownership.md says Rust owns every state, list and rule and Swift is the platform shell. Please move the new logic of this PR in a follow-up: to Rust (the crate that owns the area; the owner lists in STATUS 12147-12165 name the target per area), or at least out of the app into its package. If a declaration above is platform code (AppKit, Core Animation, OS calls, strings, tokens, DEBUG tooling), reply here and the table gets a PLATFORM row with your reason instead.

The swift-logic row is a report, not a gate: nothing blocks on this comment.

This branch was previously deployed

3 inactive (2 outdated) deployments
ci-routing-agent — 54682590 Deployed Nov 2, 2026 by cmux-bot[bot] via wait for same-key tree publisher #102328
artifacts — 37196f6a Deployed Oct 31, 2026 by teamleaderleo via add the Windows daemon to the tree #90349
sentry-dsyms — 37196f6a Deployed Oct 31, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #90349
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants