Skip to content

feat(antigravity): fetch usage per saved account via scoped agy - #3780

Open
Sogl wants to merge 4 commits into
steipete:mainfrom
Sogl:feature/antigravity-multi-account-agy
Open

Sogl wants to merge 4 commits into
steipete:mainfrom
Sogl:feature/antigravity-multi-account-agy

Conversation

@Sogl

@Sogl Sogl commented Sep 20, 2026

Copy link
Copy Markdown

Summary

Saved Antigravity Google accounts show "Limits not available" in Auto mode:
the OAuth quota endpoint 403s for many accounts, and the agy usage report is
rejected by the selected-account guard because the report carries no account
identity.

This PR makes the agy usage report account-scoped: for each saved account,
CodexBar stages that account's credentials into an isolated HOME and runs
agy /usage under that scope. The report therefore belongs to the requested
account by construction — no ambient login switching, no shared Keychain
mutation, no interactive prompts during background refresh.

How it works

  • AntigravityAgyCredentialScope builds a per-account isolated home
    (~/.codexbar/antigravity/accounts/<id>/home), stages the account's stored
    OAuth credentials where agy reads them, and serializes concurrent runs
    behind a mutation lock so parallel account refreshes can't interleave. The
    lock is acquired nonblocking (flock LOCK_NB + suspending retry), so waiters
    stay cancellation-aware and never pin a cooperative worker.
  • New logins mint credentials with the agy OAuth client (preferred over the
    IDE client) because agy rejects app-minted credentials; the minting client
    is persisted into each credential. Refresh keeps the issuer's client: stored
    client fields are used when present, and credentials saved before those
    fields existed fall back to the installed app's client — the same resolution
    as before this change, so existing grants keep refreshing.
  • agy stderr is classified: eligibility/TOS rejections surface as
    cliAccountNotEligible with an actionable message instead of a silent
    "Limits not available"; auth-required maps to the existing re-login guidance.
  • The scoped report runs first on a warm-path miss; if it fails (for example
    agy older than 1.1.11 or an unrecognized version), the existing
    identity-checked ambient spawn fallback runs as before, so setups whose
    legacy CLI source works keep their quotas.
  • Without agy installed, behavior is unchanged: app-local/ide-local probes +
    account-scoped OAuth + offline fallback, plus the same eligibility
    diagnostics.

Safety / platform notes

  • Ambient agy and IDE sessions are never touched — the scope is a directory
    of staged files, not a login change. Removing an account writes a persistent
    retirement marker under accounts/.retired/ before deleting its directory,
    so queued or in-flight refreshes — in this process or a separate codexbar
    CLI invocation sharing the lock — cannot restage credentials for a removed
    account; a first scoped operation in each process also sweeps staged homes
    left behind by an interrupted removal.
  • Scoped runs are serialized (one agy process at a time), so a stacked
    four-account refresh takes tens of seconds instead of ~5s.
  • macOS-only (#if canImport(Darwin)); Linux keeps the existing OAuth path.

Test plan

  • make check — clean, 0 violations.
  • New/updated tests: AntigravityAgyCredentialScopeTests (20 — including a
    real-flock cancellation/serialization test, staged-home isolation, scope
    removal + tombstoning, two-coordinator tests covering cross-process
    retirement on a shared directory and lock, and scoped-failure → ambient-spawn
    fallback coverage), AntigravityScopedHomeRemovalTests
    (1), AntigravityUsageReportFailureTests (4), plus resolver and
    eligibility-mapping cases in AntigravityOAuthCredentialsStoreTests /
    AntigravityRemoteUsageFetcherTests (including an expired grant without
    stored client fields refreshing via the legacy app client).
  • make test — green except two pre-existing environment-dependent failures
    unrelated to this diff (pixel-tolerance CostHistoryChartMenuViewTests,
    LaunchServices-dependent BrowserDetectionTests).
  • Verified live on macOS 15.x + agy 1.2.7: four saved accounts return weekly
    quota concurrently in stacked layout; ambient agy login unchanged; no
    Keychain prompts during background refresh.

Stage each saved Google account's credentials into an isolated HOME and
run the agy CLI usage report under that scope, so every token account's
quota is fetched without mutating the ambient login, shared Keychain
items, or triggering interactive prompts. OAuth client resolution now
prefers the client embedded in the installed agy binary so newly added
accounts mint credentials the Code Assist surface accepts, and
eligibility/auth rejections surface as actionable diagnostics instead
of a silent "Limits not available".
@clawsweeper

clawsweeper Bot commented Sep 20, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 20, 2026
@clawsweeper

clawsweeper Bot commented Sep 20, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed September 20, 2026, 2:35 PM ET / 18:35 UTC (Revision 6).

ClawSweeper review

What this changes

The PR retrieves saved Antigravity accounts’ quotas through isolated agy credential directories, with account-removal cleanup, compatible OAuth refresh, diagnostics, and regression coverage.

Merge readiness

Ready for maintainer review

Current main still lacks this capability. The latest live evidence resolves the previous account-isolation proof blocker, earlier fixes remain present, and no actionable introduced defect was found.

Priority: P2
Reviewed head: b83ee6c89dc4cd68ff8e0c902724ca3a2ca3b191

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) A useful, well-supported implementation with the previous blockers addressed and relevant live account-isolation evidence.
Proof confidence 🐚 platinum hermit (4/6) Sufficient (terminal): The supplied macOS/ag y 1.2.7 terminal evidence exercises the production scoped-fetch path with distinct saved-account quotas while ambient B remains unchanged, plus fresh login, cleanup, and separate-process rejection before retired scoped staging. It resolves the previous final-result proof gap; tests supplement legacy-refresh compatibility. The downloaded Settings screenshots belong to the related guidance PR and were not used as runtime proof.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): The supplied macOS/ag y 1.2.7 terminal evidence exercises the production scoped-fetch path with distinct saved-account quotas while ambient B remains unchanged, plus fresh login, cleanup, and separate-process rejection before retired scoped staging. It resolves the previous final-result proof gap; tests supplement legacy-refresh compatibility. The downloaded Settings screenshots belong to the related guidance PR and were not used as runtime proof.
Evidence reviewed 9 items Introduced changes and policy: Read the full root AGENTS.md and the introduced production, test, and documentation changes. No nested AGENTS.md or maintainer-notes directory was found. Applied credential isolation, concurrency, and test-isolation guidance; no builds, tests, or live account probes were executed.
Pinned patch ownership: Reviewed the merge-base-to-head delta across 17 files, rather than attributing current-main drift to this PR.
Still necessary on main and latest release: Inspected the fetched main descriptor and v0.62.0: both retain the selected-account guard and suppress identity-free ambient print reports. Neither implements the proposed per-account staging path. The merged guidance in #3650 does not implement scoped fetching.
Findings None None.
Security None None.

How this fits together

CodexBar combines local Antigravity probes and Google OAuth data to display account usage. This change lets its agy CLI source retrieve quotas using each saved account’s credentials before returning account-bound usage to the app or CLI.

flowchart TD
  A[Saved Google account] --> B[Check matching local session]
  B -->|Available| F[Account usage display]
  B -->|Unavailable| C[Check retirement and acquire lock]
  C --> D[Stage isolated credentials]
  D --> E[Run agy usage report]
  E --> F
  E -->|Failure| G[Guarded CLI and OAuth fallbacks]
  G --> F
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test growth Production +1,034/−106 lines; tests +1,282/−0 lines The production growth supports credential staging, lifecycle protection, diagnostics, and provider integration, with focused regression coverage.

Technical review

Best possible solution:

Use isolated per-account agy credentials while retaining identity checks, durable cleanup, and existing OAuth and legacy CLI fallbacks.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a new scoped-fetch capability: current source confirms the intentional rejection of unbound reports, and the contributor supplies live after-change account comparisons.

Is this the best way to solve the issue?

Yes. Isolating the credential source extends saved-account coverage while preserving the existing identity guard; the documented ambient-source workaround cannot cover every saved account.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 6d3df3678a1d.

Labels

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The supplied macOS/ag y 1.2.7 terminal evidence exercises the production scoped-fetch path with distinct saved-account quotas while ambient B remains unchanged, plus fresh login, cleanup, and separate-process rejection before retired scoped staging. It resolves the previous final-result proof gap; tests supplement legacy-refresh compatibility. The downloaded Settings screenshots belong to the related guidance PR and were not used as runtime proof.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The supplied macOS/ag y 1.2.7 terminal evidence exercises the production scoped-fetch path with distinct saved-account quotas while ambient B remains unchanged, plus fresh login, cleanup, and separate-process rejection before retired scoped staging. It resolves the previous final-result proof gap; tests supplement legacy-refresh compatibility. The downloaded Settings screenshots belong to the related guidance PR and were not used as runtime proof.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove merge-risk: 🚨 security-boundary: Current PR review selected no merge-risk labels.

Label justifications:

  • P2: This improves quota retrieval for saved accounts in one provider, with an existing ambient-source workaround.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The supplied macOS/ag y 1.2.7 terminal evidence exercises the production scoped-fetch path with distinct saved-account quotas while ambient B remains unchanged, plus fresh login, cleanup, and separate-process rejection before retired scoped staging. It resolves the previous final-result proof gap; tests supplement legacy-refresh compatibility. The downloaded Settings screenshots belong to the related guidance PR and were not used as runtime proof.
  • proof: sufficient: Contributor real behavior proof is sufficient. The supplied macOS/ag y 1.2.7 terminal evidence exercises the production scoped-fetch path with distinct saved-account quotas while ambient B remains unchanged, plus fresh login, cleanup, and separate-process rejection before retired scoped staging. It resolves the previous final-result proof gap; tests supplement legacy-refresh compatibility. The downloaded Settings screenshots belong to the related guidance PR and were not used as runtime proof.

Evidence

What I checked:

Likely related people:

  • unknown: The claimed source-line change could not be verified from bounded local history. (role: source history unknown; confidence: low)
  • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (5 earlier review cycles)
  • reviewed 2026-09-20T11:26:54.731Z sha 6fbd658 :: needs real behavior proof before merge. :: [P1] [P1] Delete staged credentials when their saved account is removed | [P2] [P2] Suspend lock waiters instead of blocking cooperative workers
  • reviewed 2026-09-20T12:30:38.319Z sha 85d81c9 :: needs real behavior proof before merge. :: [P1] [P1] Share account retirement across app and CLI processes | [P1] [P1] Preserve the legacy client fallback for existing OAuth grants
  • reviewed 2026-09-20T17:04:43.375Z sha a50abdf :: needs real behavior proof before merge. :: [P1] [P1] Preserve legacy spawning when scoped reports are unsupported
  • reviewed 2026-09-20T18:20:37.749Z sha b83ee6c :: needs real behavior proof before merge. :: none
  • reviewed 2026-09-20T18:24:50.524Z sha b83ee6c :: needs real behavior proof before merge. :: none

- SettingsStore removal now deletes ~/.codexbar/antigravity/accounts/<id>
  via a coordinator hook, and the account key is tombstoned so queued or
  in-flight staging cannot restage credentials for a removed account.
- The mutation lock uses nonblocking flock(LOCK_NB) with a suspending,
  cancellation-aware wait instead of a blocking flock(LOCK_EX) that could
  stall cooperative workers while the holder awaits subprocesses.
- New tests cover the real flock lock (cancelled waiters release, lock
  reacquires), scope deletion and tombstoning, queued-staging rejection,
  removal hook wiring, and staged-home credential isolation.
@Sogl

Sogl commented Sep 20, 2026

Copy link
Copy Markdown
Author

@clawsweeper re-review

Both blocking findings addressed in 85d81c944:

[P1] Staged credentials outlive account removal — fixed. SettingsStore.removeTokenAccount now calls AntigravityAgyScopedHomeLifecycle.removeScope(accountKey:) with the saved account's UUID, which deletes ~/.codexbar/antigravity/accounts/<id>/ under the mutation lock and tombstones the account key. The tombstone is written before the deletion queues on the lock, so a fetch waiting on the lock re-checks under the lock and fails closed instead of restaging; an in-flight scoped run finishes first, then the delete lands.

  • AntigravityScopedHomeRemovalTests — settings → coordinator wiring (removal requests scoped-home deletion by account UUID).
  • removeScope deletes staged home and blocks restaging — directory removed; prepare and withPreparedScope both reject afterwards.
  • queued staging cannot restage a removed account — a fetch queued behind another scoped run sees the tombstone under the lock and never restages.

[P2] Blocking flock in cooperative pool — fixed. AntigravityAgyCredentialMutationLock now acquires with flock(fd, LOCK_EX | LOCK_NB) and suspends via Task.sleep on EWOULDBLOCK, so waiters never pin a cooperative worker while the holder awaits subprocesses, and cancellation abandons the wait promptly.

  • real mutation lock releases cancelled waiters and reacquires — exercises the production flock lock (not the fake lock): a cancelled waiter finishes immediately instead of hanging in a blocked syscall, and a later waiter acquires the lock after the holder releases.

Account binding / isolation evidencestaged home exposes only the scoped account token proves the scoped HOME contains exactly one file: the agy file-token payload minted from the selected account's stored grant. The child env pins HOME/PWD/SSH_TTY, so agy selects file token storage rather than the ambient keyring — ambient credentials are never on a path the scoped agy reads. The existing grant check (prepare replaces staged token from a different grant) additionally guarantees a stale staged grant from different credentials is always replaced before any subprocess runs.

Expiry/refreshprepare keeps fresher staged token and replaces staler one covers the expired-grant path (agy's own refreshed token for the same grant is kept; an older injected credential never clobbers it), and refresh uses the client fields stored in each credential file (covered in AntigravityRemoteUsageFetcherTests).

@clawsweeper

clawsweeper Bot commented Sep 20, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper clawsweeper Bot removed the merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. label Sep 20, 2026
Retirement markers under accounts/.retired make account removal visible to
every process sharing the staged directories: a queued CLI fetch can no
longer restage a removed account's grant, and a first scoped operation
sweeps homes left behind by an interrupted removal.

Refresh fallback for credentials without stored client fields resolves the
installed app's OAuth client again, matching the grants' issuer; the
agy-first preference stays scoped to new logins.
@Sogl

Sogl commented Sep 20, 2026

Copy link
Copy Markdown
Author

@clawsweeper re-review

Both Revision-2 findings addressed in a50abdf49:

[P1] Share account retirement across processes — retirement is now persisted on the shared filesystem. removeScope writes a marker at accounts/.retired/<sanitized-key> before queueing the directory deletion on the mutation lock, and isScopeRetired (consulted on the fast path and re-checked under the lock) treats the marker as authoritative. A separate codexbar CLI process that captured the account before removal and acquires the shared flock afterwards now hits the marker and fails closed instead of restaging the grant. Additionally, each process reconciles once under the lock before its first scoped operation: staged homes whose markers already exist are deleted, so a removal interrupted by a crash still completes rather than leaving reusable tokens on disk.

[P1] Legacy refresh fallback — the shared resolver is split. resolvedClient() keeps the agy-first order and now serves only new logins (which persist the minting client into the credential fields). The fetcher's refresh fallback uses the new legacyRefreshClient() = environment override → installed-app client, byte-identical to the pre-change resolution, so existing grants minted by the IDE client keep refreshing with their issuer.

Coverage added:

  • queued staging in another coordinator cannot restage a removed account — two coordinators sharing one directory and one real flock file; the second coordinator's fetch queues behind the first's locked operation, removal lands mid-wait, the queued fetch is rejected before any I/O.
  • removeScope blocks restaging from another coordinator sharing the directory — a second coordinator with an empty in-memory tombstone is blocked by the persisted marker.
  • first scoped operation sweeps staged home left by interrupted removal — marker present, directory leftover; the next scoped operation in another coordinator completes the deletion under the lock.
  • remote refresh of legacy grant without client fields uses fallback resolver — expired grant without stored client_id/client_secret refreshes with the resolver-supplied (legacy app) client.
  • legacy refresh client resolves installed app client / is nil without installed app — resolver unit coverage via injected application roots.

Verified live: removing all four saved accounts produced four staged home removed events plus four .retired markers; re-adding created fresh UUIDs whose staging and reports are unaffected by prior markers.

@clawsweeper

clawsweeper Bot commented Sep 20, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. label Sep 20, 2026
@clawsweeper

clawsweeper Bot commented Sep 20, 2026

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@Sogl

Sogl commented Sep 20, 2026

Copy link
Copy Markdown
Author

Revision 3 follow-up — commit b83ee6c89

[P1] Preserve legacy spawning when scoped reports are unsupported — fixed

fetchUsingWarmSession no longer returns early when the account-scoped report
fails. The scoped print is still attempted first; on any non-cancellation
error (agy < 1.1.11, unrecognized version string, subprocess failure) it falls
through to the existing spawnFetch path, which keeps its own CSRF-version
gate, and its result is still identity-validated by
AntigravitySelectedAccountGuard in fetchWithReportFallback. Cancellation
still propagates without spawning.

Regression tests:

  • account scoped fetch failure falls back to ambient spawn
  • account scoped fetch cancellation does not spawn

Production evidence (macOS, agy 1.2.7, this build)

Redacted excerpts. Emails appear only as accountFingerprint hashes; UUIDs
are CodexBar-internal account keys.

Separate process rejects a retired account before provider I/O

A retirement marker was written to accounts/.retired/8A0DF9AE-… (simulating
a removal performed by another process), then the packaged CLI ran in its own
process: codexbar usage --provider antigravity --all-accounts --log-level debug.
The CLI's independent coordinator observed the persisted marker and refused
staging — no token file was written, no agy was spawned for that account:

accountKey=1F468146-… agy scope: token staged → prepared → report succeeded
accountKey=8A0DF9AE-… agy scope: staging skipped, account scope removed
accountKey=8A0DF9AE-… Antigravity account-scoped report failed:
    account scope was removed
accountKey=55C7A5E4-… agy scope: token staged → prepared → report succeeded

The same run also exercised the new fallback chain end-to-end: the blocked
scoped report fell through to the ambient spawn, the CSRF-version gate
rejected it on agy 1.2.7, the ambient print report stayed suppressed
(account-scoped data required), and the account was served by the OAuth
strategy instead.

A first CLI run additionally swept the stale staged home left behind:
accounts/8A0DF9AE-…/ was removed by the separate process via the
reconciliation pass, while .retired/8A0DF9AE-… persisted.

Scoped fetch per selected account

Ambient IDE was not running and the warm agy scan missed, so each selected
account fetched through its own staged HOME:

Antigravity warm path missed; running account-scoped print report expectedAccount=ee765f6fc6
agy scope: waiting for mutation lock accountKey=8A0DF9AE-…
agy scope: token staged accountKey=8A0DF9AE-… action=kept-fresher-staged
    tokenFile=~/.codexbar/antigravity/accounts/8A0DF9AE-…/home/.gemini/antigravity-cli/antigravity-oauth-token
agy scope: prepared accountKey=8A0DF9AE-… home=~/.codexbar/antigravity/accounts/8A0DF9AE-…/home
agy version probe scope=account-scoped version=1.2.7
agy scope: finished accountKey=8A0DF9AE-…
Antigravity account-scoped report succeeded accountKey=8A0DF9AE-… usage=windows=2 extra=2

Switching between three saved accounts produced three distinct fingerprints
(ee765f6fc6, b24b095681, 2bd5bfb1bf), each staging only its own token
file under accounts/<uuid>/home/.

Removal cleanup + persistent tombstone

Token account removed count=3 provider=antigravity
agy scope: staged home removed accountKey=6C053EE3-…

$ ls ~/.codexbar/antigravity/accounts/.retired/
6C053EE3-82FB-4622-82FC-44409E6D93D1   ← durable cross-process marker

Fresh login

Token account added count=2 provider=antigravity
agy scope: token staged accountKey=6C053EE3-… action=written credentialsExpiry=…
Antigravity account-scoped report succeeded accountKey=6C053EE3-…

All four re-added accounts staged and fetched on first refresh after login.

Expired legacy grant

No live trace: reproducing it requires a pre-PR grant whose access token
expires on demand. Covered by tests instead:

  • legacyRefreshClient resolves env → installed IDE client (main's order)
  • remote refresh of legacy grant without client fields uses fallback resolver
    — an expired grant with no stored client_id/client_secret refreshes via
    the IDE client, not the agy-first login resolver

Grants carrying stored client fields still pin to them; the fallback order is
unchanged from main for grants that lack them.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Sep 20, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. labels Sep 20, 2026
@Sogl

Sogl commented Sep 20, 2026

Copy link
Copy Markdown
Author

Account-isolation proof: ambient B vs scoped A (live, this build)

Setup: ambient agy (~/.gemini/antigravity-cli/antigravity-oauth-token,
untouched) is logged into account B (ag***@gmail.com), which is also one of
the saved accounts. CodexBar has three saved accounts: ps***, pa***,
ag*** @gmail.com.

1. Ambient run — plain agy -p "/usage" --output-format json under the
default HOME (account B):

Gemini Models    Weekly Limit Remaining   0%   reset 2026-09-23T10:04:56Z
Claude and GPT   Weekly Limit Remaining   0%   reset 2026-09-23T14:58:41Z

2. Scoped runcodexbar usage --provider antigravity --all-accounts,
each saved account through its own staged HOME, ambient session untouched:

ps***@gmail.com:  Gemini 0% (resets 2d 18h), Claude/GPT 0% (resets 4d 13h)
pa***@gmail.com:  Gemini 0% (resets 2d 19h) — no Claude/GPT bucket at all
ag***@gmail.com:  Gemini 0% (resets 2d 15h), Claude/GPT 0% (resets 2d 20h)
                  — identical to the ambient B report above

3. Staged credential identityid_token email claims differ per staged
home (emails masked):

accounts/1F468146-…/home/…/antigravity-oauth-token → ps***@gmail.com
accounts/55C7A5E4-…/home/…/antigravity-oauth-token → ag***@gmail.com
accounts/8A0DF9AE-…/home/…/antigravity-oauth-token → pa***@gmail.com

If agy had silently consumed ambient credentials, the pa*** report would
have returned B's two-bucket shape; instead it produced a different quota
structure for a different account, and ps*** returned distinct reset times.
Ambient B stayed authenticated and unchanged throughout.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Sep 20, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Sep 20, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. labels Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Antigravity "Limits not available" bug.

1 participant