feat(status-bar): Antigravity usage status - #7996
Conversation
- Guard auth.json read/parse so missing files return null - Thread AbortSignal through Grok rate-limit fetch and ACP auth - Pass isRemote:false for floating-terminal agent launch env
Merge stablyai#7878 (fix/antigravity-usage-status) onto main as the first half of the combined Antigravity + Grok usage status replacement PR.
Merge stablyai#7878 and stablyai#7901 into one replacement branch: - Keep both providers in shared unions, defaults, RPC ui.set schema, locales - Wire Antigravity into rate-limit fetch lifecycle (mirror Gemini snapshot) - Preserve Grok managed accounts, GROK_HOME, and usage fetch from stablyai#7901 - Accept grok and _grokStatusBarDefaultAdded on runtime ui.set
|
@coderabbitai review Please re-review this combined Antigravity + Grok usage status PR (replacement for #7878 and #7901). |
|
✅ Action performedReview finished.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds managed Grok account lifecycle management, isolated home directories, CLI authentication, billing-based rate-limit fetching, and IPC/preload integration. Grok homes now flow through session scanning, PTY and WSL environment handling, launch resolution, and rate-limit refreshes. Antigravity and Grok are added to shared provider state, status-bar visibility, settings controls, persistence migration, localization, and web fallbacks. Extensive tests cover account operations, authentication, environment routing, session discovery, provider visibility, and UI migrations. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/renderer/src/components/status-bar/StatusBar.tsx (1)
1685-1699: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winGrok's letter badge collides with Codex's fallback letter.
grokis explicitly mapped to'X', butcodexhas no explicit branch in this ternary and falls through to the same'X'default. IniconOnlymode both Codex and Grok will render an identical single-letter badge, making them indistinguishable.🐛 Proposed fix — give Codex its own letter
{provider.provider === 'claude' ? 'C' : provider.provider === 'gemini' ? 'G' : provider.provider === 'opencode-go' ? 'O' : provider.provider === 'kimi' ? 'K' - : provider.provider === 'antigravity' - ? 'A' - : provider.provider === 'grok' - ? 'X' - : provider.provider === 'minimax' - ? 'M' - : 'X'} + : provider.provider === 'antigravity' + ? 'A' + : provider.provider === 'grok' + ? 'X' + : provider.provider === 'minimax' + ? 'M' + : provider.provider === 'codex' + ? 'D' + : 'X'}src/main/ipc/pty.ts (1)
496-501: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winAdd a Grok restoration mirror for shell-ready PTYs.
src/main/ipc/pty.tsinjectsGROK_HOME, but onlyCODEX_HOMEhas anORCA_*companion and shell-ready restore path insrc/main/providers/local-pty-provider.ts. Managed Grok sessions can be overridden by shell rc re-exports unless Grok gets the same restore hook.
🧹 Nitpick comments (9)
src/renderer/src/components/status-bar/status-bar-agent-gating.ts (1)
3-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate "Why:" comment line left behind.
Lines 3 and 4 both open with "// Why:" restating the same rationale ("...usage bars are surface noise when the underlying..."). This reads as a stray duplicate from a merge/rebase rather than one clean explanation.
✏️ Proposed cleanup
-// Why: Claude/Codex/Gemini/Antigravity usage bars are surface noise when the underlying -// Why: CLI-backed usage bars are surface noise when the underlying +// Why: CLI-backed usage bars are surface noise when the underlying // CLI isn't installed (e.g. a fresh Ubuntu install showing "Gemini Usage"src/renderer/src/components/settings/appearance-status-bar-usage-toggles.ts (1)
138-167: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAntigravity locale keys break the hash-based key convention used elsewhere in this file.
Every other entry uses 10-char hash keys (e.g.
9dc15020d7,de50c6f516), but the antigravity entry uses readable keys (antigravityUsageTitle,antigravityUsageDescription,antigravityKeyword). Based on learnings, settings components should use hash-based locale keys generated viapnpm bootstrap:locale-catalogfor consistency with the rest of the catalog.✏️ Suggested direction
- title: translate( - 'auto.components.settings.appearance.search.antigravityUsageTitle', - 'Antigravity Usage' - ), - description: translate( - 'auto.components.settings.appearance.search.antigravityUsageDescription', - 'Show Antigravity subscription usage in the status bar.' - ), + title: translate('auto.components.settings.appearance.search.<hash1>', 'Antigravity Usage'), + description: translate( + 'auto.components.settings.appearance.search.<hash2>', + 'Show Antigravity subscription usage in the status bar.' + ),Based on learnings: "use hash-based locale keys with
translate('auto.components.<Dir>.<ComponentFile>.<10-char-hash>', 'Default English text')... runpnpm bootstrap:locale-catalogso translations propagate toes/ja/ko/zh."Source: Learnings
src/renderer/src/components/settings/appearance-status-bar-search.ts (1)
10-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMerge helper correctly papers over the duplicate catalogs, but see the root-cause comment.
mergeUsageStatusBarToggles()is a reasonable stopgap, and the inline "Why" comment appropriately explains the rationale per path instructions for non-obvious code. However, the underlying duplication betweengetUsageStatusBarToggles()andgetUsageStatusBarToggleEntries()(flagged inappearance-status-bar-usage-toggles.ts) means shared entries can drift sinceMap.setsilently prefers whichever source runs second for overlapping ids.src/renderer/src/lib/resume-sleeping-agent-session.ts (1)
53-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse the already-computed platform instead of recomputing.
isRemoteResumeLaunch(record.worktreeId)re-invokesgetResumeLaunchPlatform(anotheruseAppStore.getState()+ worktree/repo/runtime lookups) even thoughresumeLaunchPlatformis already available on Line 53. DerivingisRemotefrom the local value avoids the redundant work and guarantees the two derived values can't diverge.♻️ Proposed change
- : resolveTuiAgentLaunchEnv(record.agent, state.settings?.agentDefaultEnv, { - settings: state.settings, - isRemote: isRemoteResumeLaunch(record.worktreeId), - launchPlatform: resumeLaunchPlatform, - hostPlatform: CLIENT_PLATFORM - }), + : resolveTuiAgentLaunchEnv(record.agent, state.settings?.agentDefaultEnv, { + settings: state.settings, + isRemote: resumeLaunchPlatform !== CLIENT_PLATFORM, + launchPlatform: resumeLaunchPlatform, + hostPlatform: CLIENT_PLATFORM + }),src/renderer/src/lib/onboarding-folder-agent-startup.ts (1)
22-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse the shared
CLIENT_PLATFORMconstant instead of a local re-implementation.
getClientPlatform()duplicatesCLIENT_PLATFORMfromsrc/renderer/src/lib/new-workspace.ts, which every other file touched in this PR already imports for the same purpose. This diff calls the local duplicate twice more (launchPlatform,hostPlatform), compounding the divergence risk if the two implementations ever drift.♻️ Suggested consolidation
-function getClientPlatform(): NodeJS.Platform { - if (navigator.userAgent.includes('Windows')) { - return 'win32' - } - return navigator.userAgent.includes('Mac') ? 'darwin' : 'linux' -} +import { CLIENT_PLATFORM } from './new-workspace'- agentEnv: resolveTuiAgentLaunchEnv(agent, settings.agentDefaultEnv, { - settings, - launchPlatform: getClientPlatform(), - hostPlatform: getClientPlatform() - }), - platform: getClientPlatform(), + agentEnv: resolveTuiAgentLaunchEnv(agent, settings.agentDefaultEnv, { + settings, + launchPlatform: CLIENT_PLATFORM, + hostPlatform: CLIENT_PLATFORM + }), + platform: CLIENT_PLATFORM,Also applies to: 47-51
src/shared/tui-agent-launch-defaults.ts (1)
108-129: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueRemove the no-op Grok branch. Both paths here return the same
env, and the main PTY path already owns managedGROK_HOMEinjection. Drop the unused platform/settings plumbing or wire it to the actual injection point.src/main/ai-vault/session-scanner-source-discovery.ts (1)
164-170: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a "why" comment for
additionalGrokSessionsDirs.The merge of
additionalGrokSessionsDirsinto the discovery root list is a non-obvious addition (presumably to cover managed/isolated Grok homes) with no comment explaining the rationale. As per coding guidelines, "When writing or modifying code driven by a design doc or another non-obvious constraint, add a brief comment explaining why the code behaves that way."📝 Proposed comment
return [ + // Why: managed Grok accounts keep sessions under isolated GROK_HOME + // directories outside the default `~/.grok/sessions` path, so scanning + // must include each managed account's sessions dir explicitly. ...sessionRootDirs(options.grokSessionsDir ?? GROK_SESSIONS_DIR, wslHomeDirs, [ '.grok', 'sessions' ]), ...(options.additionalGrokSessionsDirs ?? []) ].map((rootDir) =>Source: Coding guidelines
src/renderer/src/components/settings/GrokAccountsSection.tsx (1)
60-60: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueWiden return type to
React.ReactNode.Static analysis flags
JSX.Elementas too narrow for a component's return type since it excludesnull, strings, and fragments.♻️ Proposed fix
-export function GrokAccountsSection(): JSX.Element { +export function GrokAccountsSection(): React.ReactNode {Source: Linters/SAST tools
src/shared/types.ts (1)
2332-2348: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
GrokManagedAccountandGrokManagedAccountSummaryare identical.Both types declare the exact same fields. If the intent mirrors the Codex/Claude full-vs-summary split (redacting sensitive fields before exposing accounts to the renderer), there's currently nothing to redact, so the duplication buys nothing today and risks drifting out of sync if a sensitive field is later added to the full type but not mirrored (or over-mirrored) into the summary type.
♻️ Suggested consolidation
-export type GrokManagedAccountSummary = { - id: string - email: string - managedHomePath: string - createdAt: number - updatedAt: number - lastAuthenticatedAt: number -} +// Why: no sensitive fields currently differ between the persisted account and +// the renderer-facing summary; alias instead of maintaining two copies that +// can silently drift. +export type GrokManagedAccountSummary = GrokManagedAccount
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 3e9fed51-7afa-4678-ae29-d12ed88feb5b
📒 Files selected for processing (88)
src/main/ai-vault/session-scanner-grok-managed.test.tssrc/main/ai-vault/session-scanner-source-discovery.tssrc/main/ai-vault/session-scanner-types.tssrc/main/codex-accounts/runtime-home-service.test.tssrc/main/codex-accounts/service.test.tssrc/main/daemon/pty-subprocess.test.tssrc/main/daemon/pty-subprocess.tssrc/main/grok-accounts/grok-auth-file.tssrc/main/grok-accounts/managed-home.test.tssrc/main/grok-accounts/managed-home.tssrc/main/grok-accounts/service.test.tssrc/main/grok-accounts/service.tssrc/main/index.tssrc/main/ipc/ai-vault.test.tssrc/main/ipc/ai-vault.tssrc/main/ipc/grok-accounts.test.tssrc/main/ipc/grok-accounts.tssrc/main/ipc/pty.test.tssrc/main/ipc/pty.tssrc/main/ipc/register-core-handlers.test.tssrc/main/ipc/register-core-handlers.tssrc/main/providers/local-pty-provider.test.tssrc/main/providers/local-pty-provider.tssrc/main/rate-limits/codex-fetcher-auth-errors.test.tssrc/main/rate-limits/codex-fetcher-pty-settle.test.tssrc/main/rate-limits/grok-acp-auth.tssrc/main/rate-limits/grok-fetcher.test.tssrc/main/rate-limits/grok-fetcher.tssrc/main/rate-limits/service.test.tssrc/main/rate-limits/service.tssrc/main/runtime/orca-runtime-grok-launch-env.test.tssrc/main/runtime/orca-runtime.tssrc/main/runtime/rpc/methods/client-ui.test.tssrc/main/runtime/rpc/methods/client-ui.tssrc/main/startup/configure-process.test.tssrc/main/startup/configure-process.tssrc/main/window/attach-main-window-services.tssrc/preload/api-types.tssrc/preload/index.tssrc/renderer/src/components/floating-terminal/FloatingTerminalWindowControls.tsxsrc/renderer/src/components/settings/AccountsPane.tsxsrc/renderer/src/components/settings/AgentsPane.tsxsrc/renderer/src/components/settings/AppearancePane.test.tsxsrc/renderer/src/components/settings/AppearanceWindowSidebarSection.tsxsrc/renderer/src/components/settings/GrokAccountsSection.tsxsrc/renderer/src/components/settings/accounts-search.tssrc/renderer/src/components/settings/appearance-status-bar-search.test.tssrc/renderer/src/components/settings/appearance-status-bar-search.tssrc/renderer/src/components/settings/appearance-status-bar-usage-toggle-entries.tssrc/renderer/src/components/settings/appearance-status-bar-usage-toggles.tssrc/renderer/src/components/status-bar/StatusBar.tsxsrc/renderer/src/components/status-bar/status-bar-agent-gating.test.tssrc/renderer/src/components/status-bar/status-bar-agent-gating.tssrc/renderer/src/components/status-bar/status-bar-provider-visibility.test.tssrc/renderer/src/components/status-bar/status-bar-provider-visibility.tssrc/renderer/src/components/status-bar/tooltip.test.tssrc/renderer/src/components/status-bar/tooltip.tsxsrc/renderer/src/components/status-bar/usage-error-copy.test.tssrc/renderer/src/components/status-bar/usage-error-copy.tssrc/renderer/src/components/terminal-pane/pty-connection.tssrc/renderer/src/hooks/useComposerState.tssrc/renderer/src/hooks/useIpcEvents.test.tssrc/renderer/src/i18n/locales/en.jsonsrc/renderer/src/i18n/locales/es.jsonsrc/renderer/src/i18n/locales/ja.jsonsrc/renderer/src/i18n/locales/ko.jsonsrc/renderer/src/i18n/locales/zh.jsonsrc/renderer/src/lib/ai-vault-resume-command.tssrc/renderer/src/lib/github-work-item-background-request.tssrc/renderer/src/lib/launch-agent-background-session.tssrc/renderer/src/lib/launch-agent-in-new-tab.tssrc/renderer/src/lib/launch-work-item-direct-agent.tssrc/renderer/src/lib/onboarding-folder-agent-startup.tssrc/renderer/src/lib/resume-sleeping-agent-launch-platform.tssrc/renderer/src/lib/resume-sleeping-agent-session.tssrc/renderer/src/lib/worktree-activation.tssrc/renderer/src/store/slices/rate-limits.test.tssrc/renderer/src/store/slices/rate-limits.tssrc/renderer/src/store/slices/ui.test.tssrc/renderer/src/store/slices/ui.tssrc/renderer/src/web/web-preload-api.tssrc/shared/constants.tssrc/shared/rate-limit-types.test.tssrc/shared/rate-limit-types.tssrc/shared/status-bar-defaults.tssrc/shared/tui-agent-launch-defaults.test.tssrc/shared/tui-agent-launch-defaults.tssrc/shared/types.ts
- Pin WSL shell distro when resolving managed GROK_HOME (parity with Codex) - Refresh only Grok on account change via fetchGrokOnly - Consolidate usage status-bar toggle catalogs; add Grok locale keys - Fix Grok aria-label, feature-interaction tracking, and test fixture
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/renderer/src/components/settings/appearance-status-bar-usage-toggle-entries.ts (1)
1-7: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove the unused shim export. No files reference
appearance-status-bar-usage-toggle-entries, so this re-export can be deleted.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: dabd12d0-d135-441a-bf89-f98018af8bc9
📒 Files selected for processing (12)
src/main/daemon/pty-subprocess.tssrc/main/rate-limits/service.tssrc/renderer/src/components/settings/appearance-status-bar-search.tssrc/renderer/src/components/settings/appearance-status-bar-usage-toggle-entries.tssrc/renderer/src/components/settings/appearance-status-bar-usage-toggles.tssrc/renderer/src/components/status-bar/StatusBar.tsxsrc/renderer/src/components/status-bar/status-bar-provider-visibility.test.tssrc/renderer/src/i18n/locales/en.jsonsrc/renderer/src/i18n/locales/es.jsonsrc/renderer/src/i18n/locales/ja.jsonsrc/renderer/src/i18n/locales/ko.jsonsrc/renderer/src/i18n/locales/zh.json
✅ Files skipped from review due to trivial changes (1)
- src/renderer/src/i18n/locales/en.json
🚧 Files skipped from review as they are similar to previous changes (8)
- src/renderer/src/components/settings/appearance-status-bar-usage-toggles.ts
- src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
- src/main/daemon/pty-subprocess.ts
- src/renderer/src/i18n/locales/ko.json
- src/renderer/src/i18n/locales/ja.json
- src/renderer/src/i18n/locales/es.json
- src/renderer/src/components/status-bar/StatusBar.tsx
- src/renderer/src/i18n/locales/zh.json
Remove the leftover re-export path so Appearance search has a single source of truth for usage provider toggles (including Antigravity + Grok).
Keep Grok accounts section imports with remote provider account client helpers from stablyai#7999, and preserve both status-bar usage + remoteServer locale keys.
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 8bccc9c1-db2a-4a59-b99c-b0e161cb5806
📒 Files selected for processing (9)
src/main/codex-accounts/service.test.tssrc/main/runtime/orca-runtime.tssrc/renderer/src/components/settings/AccountsPane.tsxsrc/renderer/src/components/status-bar/StatusBar.tsxsrc/renderer/src/i18n/locales/en.jsonsrc/renderer/src/i18n/locales/es.jsonsrc/renderer/src/i18n/locales/ja.jsonsrc/renderer/src/i18n/locales/ko.jsonsrc/renderer/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (3)
- src/main/codex-accounts/service.test.ts
- src/renderer/src/components/status-bar/StatusBar.tsx
- src/main/runtime/orca-runtime.ts
Re-do AccountsPane three-way merge with binary-safe git objects and keep both Grok accounts + remote provider client imports. Rebuild locale JSON merges so em dash/ellipsis/middle-dot strings are no longer mojibake.
Deep-merge locale JSON from binary-safe git objects so PR usage keys and main remote-server strings coexist without conflict markers or mojibake.
|
Merged latest |
|
Merged latest |
Bring in browser CDP attach, HTML preview-to-side, and Antigravity sandbox flag updates from main. No conflicts expected with this branch's status-bar/Grok surfaces.
|
Merged latest |
Prefer PR managed Grok accounts + Antigravity usage over main stablyai#7869 minimal CLI status surfaces. Deduplicate auto-merged Grok IPC/preload registrations and deep-merge locale catalogs.
|
Merged latest |
Grok usage landed on main via stablyai#7869 (superseding this PR's stablyai#7901 lineage), so this merge keeps main's Grok implementation everywhere the two stacks overlapped and drops the PR-side Grok stack (managed accounts/GROK_HOME, fetcher, launch/resume env, appearance catalog). The PR now carries only the Antigravity usage surfaces.
… usage-history dedupe)
RateLimitState gained a required antigravity field; the pane fixture must carry it to typecheck.
…reconciliation The fork-side merge (3867ad0) resolved against main@fa2b228ad keeping both usage stacks. Main's Grok implementation (stablyai#7869) already covers Grok, so the maintainer-side resolution (58745b2 + 46cfc00) that reduces this PR to Antigravity-only wins; this merge records that supersession.
|
Maintainer note (@bbingz): Grok usage landed on main via #7869, so I reconciled this branch down to Antigravity-only rather than carrying two competing Grok stacks:
If Grok managed accounts / Validation on the reconciled tip: |
|
Thanks @brennanb2025 — this reconciliation looks right. Keeping main’s Grok from #7869 and narrowing this PR to Antigravity-only avoids two competing stacks. I’m fine with dropping the fork-side Grok managed accounts / Appreciate you landing the Antigravity path cleanly and validating typecheck / focused tests / lint on the tip. |
|
First off — thank you for all the work you've put into this PR, and for being so gracious about the Grok reconciliation. We appreciate the offer to rebuild the managed-accounts piece on the new base! That said, please hold off on that fresh PR — we don't want to add GROK_HOME isolation until we've done real research and planned it out. Our CODEX_HOME managed-home experience surfaced a lot of subtle issues (config write-back/mirroring churn, WSL/remote env injection surface), so we want to design any second owned-home deliberately rather than inherit that class of problems. Today's read-only ~/.grok/auth.json integration covers usage visibility without any of that surface. If multi-account demand or a write-access need materializes, we'll do the design work and drive it from our side — we wouldn't ask you to build it twice. Thanks again for the Antigravity work — it's ready to go, and we're glad to have it. |
…opt-in The Antigravity snapshot mirrors the Gemini fetch, which is permanently 'unavailable' until the user opts into Gemini CLI OAuth. Without this gate the default-on checked item plus a detected agy CLI pinned a dead 'A --' bar (Gemini itself hides in that state) and suppressed the usage setup CTA for users who configured nothing.
Replace the Gemini-mirrored Antigravity snapshot (stablyai#7996) with a real Code Assist ANTIGRAVITY fetch, OS keyring credential reads (agy), encrypted multi-account store, and a status-bar account switcher. Why: stablyai#7996 landed the status-bar slot but mirrored Gemini OAuth usage, which does not match Antigravity quota and requires Gemini CLI login. This upgrade reads agy/keyring credentials, groups family limits like the Antigravity app, and lets users switch Google accounts from Orca.
Summary
Antigravity usage visibility in the status bar (originally #7878). This PR previously also carried a Grok usage stack (#7901 lineage); Grok usage has since landed on main via #7869, so this PR has been reconciled down to Antigravity only — main's Grok implementation is kept everywhere the two overlapped.
Behavior
ui.setschema (antigravityitem +_antigravityStatusBarDefaultAddedone-shot migration), and rate-limit state.provider: 'antigravity'(Antigravity shares Google/Gemini usage credentials today) so the bar gets a real fetch lifecycle instead of staying pending.geminiCliOAuthEnabled), is the durable visibility signal — Antigravity has no separate persisted usage credential in Orca. Without the OAuth opt-in the mirrored snapshot is permanentlyunavailable, so the default-on item alone must not pin a dead--bar or suppress the usage setup CTA (fixed in6becd7488).Superseded / dropped
GROK_HOMEPTY env / fetcher / launch-resume paths / appearance catalog refactor) was removed in favor of main's feat(rate-limits): Grok CLI OAuth weekly credit usage #7869 implementation. If Grok managed accounts are still wanted, that should be a fresh PR against main's Grok base.Testing
pnpm typecheck— cleanagy1.1.1 from Homebrew): PATH detection, default-on toggle + context-menu round-trip, no dead bar / CTA visible with Gemini OAuth off, Gemini+Antigravity bars appear as a consistent pair with OAuth on, Antigravity details popover branding/copy.pnpm lint— oxlint, switch-exhaustiveness, reliability gates, max-lines ratchet, localization coverage all pass. Note:verify:localization-catalogfails on main too (pre-existingja.jsoninterpolation mismatch forcomponents.native-chat.composer.uploadingAttachments, unrelated to this PR).Cross-platform
Status-bar and Appearance surfaces are platform-agnostic; no keyboard shortcuts, paths, or shell behavior touched. No new IPC/preload surface beyond the
antigravityunions on existing rate-limit patterns. SSH/remote: provider unions only, same fail-closed behavior as existing providers.