Skip to content

fix(quota): keep multi-workspace fallbacks distinct#122

Merged
ndycode merged 11 commits intomainfrom
git-plan/21-issue-121-multi-workspace-quota
Mar 18, 2026
Merged

fix(quota): keep multi-workspace fallbacks distinct#122
ndycode merged 11 commits intomainfrom
git-plan/21-issue-121-multi-workspace-quota

Conversation

@ndycode
Copy link
Owner

@ndycode ndycode commented Mar 18, 2026

Summary

  • keep same-email quota cache fallbacks distinct across multi-workspace accounts
  • rebuild live fallback state after auth check and auth fix refreshes change shared-workspace identities
  • prune stale email-scoped quota cache entries after live refresh identity changes
  • isolate loaded quota cache state from failed live forecast/check/fix saves in both JSON and display paths
  • add regressions for mixed accountId rows, workspace-specific probe inputs, stale-email pruning, Windows EBUSY save failures, and concurrent quota-cache retries
  • Fixes [bug] Seem like the feature of account got muti team did not working right ? #121

Validation

  • npm run typecheck
  • npm test -- test/codex-manager-cli.test.ts test/quota-cache.test.ts
  • npm test -- test/storage.test.ts test/index.test.ts
  • npm test -- test/codex-manager-cli.test.ts

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 18, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

changes add an email-based quota fallback and thread an emailFallbackState through quota-cache, probing, refresh, health/forecast/ui, and cli flows. tests expand for multi-workspace login, quota-cache concurrency, and same-email workspace preservation. see lib/codex-manager.ts:1 and test/codex-manager-cli.test.ts:1.

Changes

Cohort / File(s) Summary
quota email fallback core
lib/codex-manager.ts
added QuotaEmailFallbackState, buildQuotaEmailFallbackState(), hasSafeQuotaEmailFallback(), cloneQuotaCacheData(). threaded emailFallbackState through getQuotaCacheEntryForAccount, updateQuotaCacheForAccount, resolveMenuQuotaProbeInput, collectMenuQuotaRefreshTargets, refreshQuotaCacheForMenu, and related flows to enable conditional email-scoped caching. (lib/codex-manager.ts:1)
cli quota & multi-workspace tests
test/codex-manager-cli.test.ts
added integration tests covering oauth refresh-token reuse preserving same-email workspaces, per-account quota writes when an email spans workspaces, pruning stale email-scoped cache entries, and preference for accountId-scoped entries; adjusted expectations for extra quota snapshot fetches. (test/codex-manager-cli.test.ts:1)
oauth plugin same-email preservation
test/index.test.ts
adds test validating manual login reuses refresh token while preserving distinct same-email workspaces. (test/index.test.ts:1)
storage dedupe test
test/storage.test.ts
adds test ensuring shared refreshToken does not erroneously match when same-email workspaces have different accountIds; deduplication preserves both accounts. (test/storage.test.ts:1)
quota-cache concurrency test
test/quota-cache.test.ts
adds test that simulates transient fs.rename errors (EBUSY/EPERM) across concurrent saveQuotaCache calls and verifies atomic save/retry behavior and final file integrity. (test/quota-cache.test.ts:1)

Sequence Diagram(s)

mermaid
sequenceDiagram
participant cli as CLI
participant manager as codex-manager
participant storage as account-storage
participant quota as quota-probe
cli->>manager: request forecast/check/fix
manager->>storage: buildQuotaEmailFallbackState(accounts)
manager->>storage: cloneQuotaCacheData / read quotaCache
alt has safe email fallback
manager->>quota: probe using email-scoped key
quota-->>manager: quota snapshot
manager->>storage: updateQuotaCacheForAccount(byEmail)
else account-id preferred
manager->>quota: probe using accountId
quota-->>manager: quota snapshot
manager->>storage: updateQuotaCacheForAccount(byAccountId)
end
manager-->>cli: results

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Concerns

  • missing regression tests: no test covers constructing emailFallbackState with inconsistent data (e.g., matchingCount != distinctAccountIds.size) to validate hasSafeQuotaEmailFallback behavior. see lib/codex-manager.ts:1.
  • windows edge cases: hasSafeQuotaEmailFallback compares emails directly; case-insensitive email normalization may cause mismatches (user@example.com vs User@Example.Com). verify normalization/locale handling in lib/codex-manager.ts:1.
  • concurrency risk: refresh paths use cloneQuotaCacheData and a local nextCache then persist; concurrent refreshes or concurrent saveQuotaCache calls could race, prune, or overwrite entries. audit callers and add cross-process concurrency tests. see lib/codex-manager.ts:1 and test/quota-cache.test.ts:1.
  • parameter threading completeness: many helpers now accept emailFallbackState; ensure all internal call sites pass the state instead of relying on defaults to avoid inconsistent computations and extra work. see lib/codex-manager.ts:1.
  • missing live-failure concurrency test: cli tests check failed live saves avoid mutating cache, but no scenario simulates concurrent live probing failures to validate no stale writes occur. add such regression in test/codex-manager-cli.test.ts:1.

Suggested labels

bug

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description covers core objectives and validation but omits risk assessment and rollback guidance required by the template. Add risk level assessment and a concrete rollback plan. Document any data migration or cache compatibility concerns given the quota cache changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed title follows conventional commits format (fix type, quota scope, 51 chars), clearly summarizes keeping multi-workspace quota fallbacks distinct.
Linked Issues check ✅ Passed pr directly addresses issue #121: quota caching now distinguishes multi-workspace accounts sharing same email via new buildQuotaEmailFallbackState, hasSafeQuotaEmailFallback, and updateQuotaCacheForAccount pruning logic [#121].
Out of Scope Changes check ✅ Passed all code changes (codex-manager.ts quota cache refactors, cli/storage/quota-cache test additions) align with issue #121 objective of distinct per-workspace quota; no unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 git-plan/21-issue-121-multi-workspace-quota
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch git-plan/21-issue-121-multi-workspace-quota
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@ndycode ndycode changed the title fix: keep multi-workspace quota rows distinct test: broaden issue 121 multi-workspace regressions Mar 18, 2026
@ndycode ndycode force-pushed the git-plan/21-issue-121-multi-workspace-quota branch from 23ad139 to 67e41fc Compare March 18, 2026 04:02
@ndycode ndycode changed the title test: broaden issue 121 multi-workspace regressions fix(quota): keep multi-workspace fallbacks distinct Mar 18, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/codex-manager.ts`:
- Around line 1628-1631: The snapshotting of quotaEmailFallbackState leads to
stale decisions when identities change during a single refresh pass; update code
so every place that mutates account identity (e.g., inside the refresh flow that
updates email/accountId and any functions that call
buildQuotaEmailFallbackState) recomputes quotaEmailFallbackState immediately
after the mutation instead of using the earlier-captured variable; replace uses
of the top-level quotaEmailFallbackState with a freshly computed const (call
buildQuotaEmailFallbackState(storage.accounts)) right after any identity update
in the refresh/token-rotation paths (refer to the refresh logic and the code
locations using quotaEmailFallbackState), and ensure all branches that call
byEmail updates/deletes use that recomputed value. Add a vitest regression that
reproduces the refresh race: create two accounts that converge to the same email
with different accountIds during one run, mirror the Windows-targeted fixture
structure from test/storage.test.ts (around the Windows IO fixtures), and assert
that byEmail updates/deletes follow the recomputed fallback state; include
handling for EBUSY/429 retry semantics per lib/** guidelines.

In `@test/codex-manager-cli.test.ts`:
- Around line 2420-2424: Replace persistent mocks with single-call mocks: for
each test that currently calls
vi.mocked(authModule.createAuthorizationFlow).mockResolvedValue(...) (and the
other similar mocks in this file), change to mockResolvedValueOnce(...) so the
mock is only applied for the single expected invocation; update the calls that
set the resolved value for createAuthorizationFlow (and the other mocked
functions at the nearby occurrences) to use mockResolvedValueOnce to document
single-call intent and avoid leaking behavior between assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1796fb81-eb49-49e7-b6f5-c5e7d114dba5

📥 Commits

Reviewing files that changed from the base of the PR and between 1d404f9 and 85e07be.

📒 Files selected for processing (4)
  • lib/codex-manager.ts
  • test/codex-manager-cli.test.ts
  • test/index.test.ts
  • test/storage.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (2)
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/storage.test.ts
  • test/codex-manager-cli.test.ts
  • test/index.test.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/codex-manager.ts
🔇 Additional comments (7)
test/storage.test.ts (1)

229-257: good regression for shared refresh-token collisions across account ids.

this case is deterministic and it validates both matching and dedup behavior for same-email/different-accountid flows (test/storage.test.ts:229-257).

lib/codex-manager.ts (2)

443-490: fallback safety and lookup precedence are solid.

the new state model and read path correctly prioritize unique accountId and only allow email fallback when safe (lib/codex-manager.ts:443-490, lib/codex-manager.ts:563-584).

Also applies to: 563-584


629-634: cloning cache before menu refresh is a good reliability improvement.

using cloneQuotaCacheData keeps refresh writes isolated until persistence, which lowers accidental in-place mutation risk in the menu flow (lib/codex-manager.ts:629-634, lib/codex-manager.ts:741-783, lib/codex-manager.ts:922-930).

Also applies to: 741-783, 922-930

test/index.test.ts (1)

2012-2080: solid regression coverage for same-email workspace preservation on manual callback.

test/index.test.ts lines 2012-2080 correctly pins the shared-refresh-token path and asserts both workspace rows remain distinct with the expected identity fields.

test/codex-manager-cli.test.ts (3)

2801-2915: good accountid-scoped cache write regression for same-email multi-workspace accounts.

test/codex-manager-cli.test.ts lines 2801-2915 cleanly verifies per-workspace byAccountId writes and prevents fallback pollution into byEmail.


2916-3028: good stale email-cache pruning regression for no-stored-accountid rows.

test/codex-manager-cli.test.ts lines 2916-3028 explicitly proves stale email-scoped cache entries are removed in the same-email multi-workspace path.


3300-3410: good precedence regression: accountid cache beats email fallback when one email spans workspaces.

test/codex-manager-cli.test.ts lines 3300-3410 validates row ordering and quota percentages from byAccountId, which is exactly the expected multi-workspace behavior.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/codex-manager.ts (1)

2297-2309: ⚠️ Potential issue | 🟠 Major

non-json forecast/fix paths still persist the stale cache object.

you now write updates into workingQuotaCache, but non-json tails still save quotaCache (lib/codex-manager.ts:2473-2475, lib/codex-manager.ts:3413-3415). this drops live probe updates in default cli output mode. please save the working copy in both paths.

also add vitest regressions for non-json forecast --live and fix --live persistence paths (e.g. test/codex-manager-cli.test.ts:1).

proposed fix
@@
- if (quotaCache && quotaCacheChanged) {
-   await saveQuotaCache(quotaCache);
- }
+ if (workingQuotaCache && quotaCacheChanged) {
+   await saveQuotaCache(workingQuotaCache);
+ }
@@
- if (quotaCache && quotaCacheChanged) {
-   await saveQuotaCache(quotaCache);
- }
+ if (workingQuotaCache && quotaCacheChanged) {
+   await saveQuotaCache(workingQuotaCache);
+ }
as per coding guidelines `lib/**`: "focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails."

Also applies to: 2384-2386, 3088-3100, 3336-3338

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/codex-manager.ts` around lines 2297 - 2309, The non-JSON "forecast" and
"fix" live paths still persist the original stale quotaCache instead of the
modified workingQuotaCache; update the persistence calls in the CLI paths that
handle --live (the code that currently writes quotaCache at the non-JSON
branches around the referenced areas) to write workingQuotaCache (the object
produced by cloneQuotaCacheData and mutated with live probe updates), ensuring
quotaCacheChanged logic still controls writes; add vitest regression tests in
test/codex-manager-cli.test.ts to cover "forecast --live" and "fix --live"
persistence (verifying the saved cache equals workingQuotaCache), and ensure
changes touch the same code paths referenced (symbols: workingQuotaCache,
quotaCache, cloneQuotaCacheData, buildQuotaEmailFallbackState, and the
forecast/fix CLI handlers) without leaking secrets.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/codex-manager.ts`:
- Around line 791-793: Add a new Vitest that reproduces concurrent-writer races
for saveQuotaCache by reusing the Windows fixture pattern from storage tests:
mock the filesystem so that some parallel writes throw EBUSY/EPERM (to trigger
the exponential backoff in lib/quota-cache.ts) while launching multiple
simultaneous calls to saveQuotaCache(...) (the call sites in codex-manager.ts
are the callers to target). The test should run several parallel saveQuotaCache
invocations, allow retries/backoff to occur, then read the cache file and assert
it contains the expected, uncorrupted JSON; ensure the mock simulates
intermittent EBUSY only for some attempts so retries are exercised and final
content is deterministic.

In `@test/codex-manager-cli.test.ts`:
- Around line 570-626: The failing tests use generic Error("save failed") so
they do not cover Windows EBUSY filesystem behavior; update the three
failure-case tests (the one using runCodexMultiAuthCli and saveQuotaCacheMock /
loadQuotaCacheMock shown here and the other two groups referenced) to add at
least one mockRejectedValueOnce that returns a Node-style errno error with code
"EBUSY" (use your test helper makeErrnoError or Error with .code="EBUSY")
instead of or in addition to new Error("save failed"), so
saveQuotaCacheMock.mockRejectedValueOnce(makeErrnoError(..., "EBUSY")) is
exercised and the assertions still expect the same unchanged originalQuotaCache
and call counts for saveQuotaCacheMock and the same payload shape for the saved
cache.
- Around line 3040-3145: The test currently asserts saveQuotaCacheMock was not
called, but the scenario intends to prune stale email-scoped entries loaded via
loadQuotaCacheMock; update the assertions after calling runCodexMultiAuthCli to
expect saveQuotaCacheMock was called once and validate the saved cache argument
no longer contains the "owner@example.com" key (inspect
saveQuotaCacheMock.mock.calls[0][0] or use
vi.mocked(saveQuotaCacheMock).mock.calls to assert saved.byEmail does not have
"owner@example.com"); keep other mocks (fetchCodexQuotaSnapshotMock,
runCodexMultiAuthCli, loadQuotaCacheMock) unchanged so the test stays
deterministic.

---

Outside diff comments:
In `@lib/codex-manager.ts`:
- Around line 2297-2309: The non-JSON "forecast" and "fix" live paths still
persist the original stale quotaCache instead of the modified workingQuotaCache;
update the persistence calls in the CLI paths that handle --live (the code that
currently writes quotaCache at the non-JSON branches around the referenced
areas) to write workingQuotaCache (the object produced by cloneQuotaCacheData
and mutated with live probe updates), ensuring quotaCacheChanged logic still
controls writes; add vitest regression tests in test/codex-manager-cli.test.ts
to cover "forecast --live" and "fix --live" persistence (verifying the saved
cache equals workingQuotaCache), and ensure changes touch the same code paths
referenced (symbols: workingQuotaCache, quotaCache, cloneQuotaCacheData,
buildQuotaEmailFallbackState, and the forecast/fix CLI handlers) without leaking
secrets.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fc1cc326-9ffd-4778-ae0b-2a05eacc0e85

📥 Commits

Reviewing files that changed from the base of the PR and between 85e07be and 6f24f63.

📒 Files selected for processing (2)
  • lib/codex-manager.ts
  • test/codex-manager-cli.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (2)
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/codex-manager-cli.test.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/codex-manager.ts
🔇 Additional comments (6)
lib/codex-manager.ts (2)

443-489: safe fallback gating looks correct and materially reduces cross-workspace cache collisions.

the split between buildQuotaEmailFallbackState and hasSafeQuotaEmailFallback, plus the canStore guard, is a good fix for ambiguous same-email ownership in lib/codex-manager.ts:443-489 and lib/codex-manager.ts:652-683.

Also applies to: 562-632, 652-683


1752-1754: good auth-rotation handling: fallback state is recomputed after identity mutation.

recomputing fallback state after email/accountid changes closes the stale-key race in refresh flows at lib/codex-manager.ts:1752-1754 and lib/codex-manager.ts:3215-3217.

Also applies to: 3215-3217

test/codex-manager-cli.test.ts (4)

2503-2605: strong regression coverage for multi-workspace fallback and refresh-race behavior.

these cases are solid and directly cover mixed same-email/accountId behavior plus token-refresh fallback recomputation at test/codex-manager-cli.test.ts:2503 (Line 2503), test/codex-manager-cli.test.ts:2925 (Line 2925), test/codex-manager-cli.test.ts:3146 (Line 3146), test/codex-manager-cli.test.ts:3543 (Line 3543), and test/codex-manager-cli.test.ts:4884 (Line 4884). this meaningfully lowers concurrency-risk regressions around fallback-state transitions.

Also applies to: 2925-3038, 3146-3271, 3543-3652, 4884-5014


2647-2661: good move to one-shot oauth mocks for determinism.

using mockResolvedValueOnce here at test/codex-manager-cli.test.ts:2647 (Line 2647) and test/codex-manager-cli.test.ts:2661 (Line 2661) keeps these tests isolated and explicit.


2718-2718: updated probe-count and cache-shape assertions look correct.

the adjusted expectations at test/codex-manager-cli.test.ts:2718 (Line 2718), test/codex-manager-cli.test.ts:2753 (Line 2753), and test/codex-manager-cli.test.ts:2796 (Line 2796) align with the new quota snapshot/cache flow and tighten behavior checks.

Also applies to: 2753-2753, 2796-2807


3273-3302: menu-loop and source-index mapping coverage is clean.

these login/settings assertions at test/codex-manager-cli.test.ts:3273 (Line 3273) and test/codex-manager-cli.test.ts:3303 (Line 3303) are deterministic and validate sort-order-to-source-index mapping clearly.

Also applies to: 3303-3434

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/codex-manager-cli.test.ts`:
- Around line 4897-5027: Add a new deterministic vitest case mirroring the
existing "recomputes live quota fallback state after refresh changes a
shared-workspace email" test but exercise the branch where the refreshed token
changes accountId while the email remains the same: set loadAccountsMock to
include two entries with the same email but different initial accountId for the
stale access token, mock queuedRefreshMock to return an access token that maps
(via mocked accountsModule.extractAccountId) to a different accountId while
extractAccountEmail still returns the same email, ensure
fetchCodexQuotaSnapshotMock and loadQuotaCacheMock setup triggers the live
fallback recompute path, then call
runCodexMultiAuthCli(["auth","fix","--live","--json"]) and assert exit code 0,
queuedRefreshMock called once, fetchCodexQuotaSnapshotMock called expected
times, saveQuotaCacheMock written with cleared byEmail/byAccountId, and
saveAccountsMock reflects the updated accountId for the refreshed token;
reference mocks/exports: runCodexMultiAuthCli, queuedRefreshMock,
loadAccountsMock, loadQuotaCacheMock, fetchCodexQuotaSnapshotMock,
saveQuotaCacheMock, saveAccountsMock, and
accountsModule.extractAccountId/extractAccountEmail to locate where to
change/add the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3e164a23-4a3e-40a7-98b0-192efa5e962c

📥 Commits

Reviewing files that changed from the base of the PR and between 6f24f63 and c5d1b85.

📒 Files selected for processing (1)
  • test/codex-manager-cli.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (1)
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/codex-manager-cli.test.ts
🔇 Additional comments (2)
test/codex-manager-cli.test.ts (2)

570-631: good windows ebusy + immutability regression coverage.

test/codex-manager-cli.test.ts:570, test/codex-manager-cli.test.ts:1319, and test/codex-manager-cli.test.ts:4849 now validate ebusy failures while asserting the originally loaded quota cache object is unchanged. this is the right guardrail for working-copy isolation.

Also applies to: 1319-1378, 4849-4895


2933-3046: good multi-workspace fallback safety coverage.

the new cases at test/codex-manager-cli.test.ts:2933, test/codex-manager-cli.test.ts:3048, test/codex-manager-cli.test.ts:3154, and test/codex-manager-cli.test.ts:3551 cover accountid/email routing boundaries well and reduce risk of collapsing same-email workspaces.

Also applies to: 3048-3153, 3154-3279, 3551-3660

@ndycode
Copy link
Owner Author

ndycode commented Mar 18, 2026

@greptile rerun

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
test/codex-manager-cli.test.ts (2)

5052-5345: ⚠️ Potential issue | 🟠 Major

mirror these refresh-drift regressions on auth check.

test/codex-manager-cli.test.ts:5052 and test/codex-manager-cli.test.ts:5183 lock down the auth fix --live --json fallback rebuilds, but the refreshed auth check path still only has generic coverage at test/codex-manager-cli.test.ts:1300 and test/codex-manager-cli.test.ts:1396. that leaves one of the two refreshed fallback branches from the pr objective unguarded.

targeted test to add
+	it("recomputes live quota fallback state during auth check when refresh changes accountId for the same email", async () => {
+		// mirror test/codex-manager-cli.test.ts:5183 with runCodexMultiAuthCli(["auth", "check"])
+		// assert stale byEmail fallback is cleared or re-keyed after refresh
+	});

As per coding guidelines test/**: tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/codex-manager-cli.test.ts` around lines 5052 - 5345, Add two new vitest
tests in test/codex-manager-cli.test.ts that mirror the existing "recomputes
live quota fallback state after refresh changes a shared-workspace email" and
"recomputes live quota fallback state after refresh changes accountId for the
same email" cases but call
runCodexMultiAuthCli(["auth","check","--live","--json"]) instead of "fix";
reproduce the same mock setups for loadAccountsMock, loadQuotaCacheMock,
queuedRefreshMock, accountsModule.extractAccountId,
accountsModule.extractAccountEmail, fetchCodexQuotaSnapshotMock, and spies
(console.log) and assert the same outcomes (exit code 0, queuedRefreshMock
called once, fetchCodexQuotaSnapshotMock twice, saveQuotaCacheMock and
saveAccountsMock called with the expected byAccountId/byEmail shape and
account/email changes, and that the JSON reports contain two "healthy" reports)
to ensure deterministic coverage of both refreshed fallback branches for the
"auth check" path.

3164-3229: ⚠️ Potential issue | 🟠 Major

prove the stale email fallback never reaches the menu.

test/codex-manager-cli.test.ts:3164 seeds an unsafe byEmail["owner@example.com"] entry, but test/codex-manager-cli.test.ts:3226 only asserts that probing and saving were skipped. if the login menu still renders that stale fallback for both rows, this regression still passes while the original same-email display bug survives.

suggested assertion
 		expect(exitCode).toBe(0);
 		expect(fetchCodexQuotaSnapshotMock).not.toHaveBeenCalled();
 		expect(saveQuotaCacheMock).not.toHaveBeenCalled();
+		const menuAccounts = promptLoginModeMock.mock.calls[0]?.[0] as Array<{
+			quota5hLeftPercent?: number;
+		}>;
+		expect(
+			menuAccounts.every((account) => account.quota5hLeftPercent == null),
+		).toBe(true);
 	});

As per coding guidelines test/**: tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/codex-manager-cli.test.ts` around lines 3164 - 3229, The test seeds a
stale byEmail entry but never asserts the login menu didn't show that stale
email; update the test around runCodexMultiAuthCli to explicitly assert that the
mocked menu (promptLoginModeMock) was not passed any choices containing
"owner@example.com" (i.e., inspect promptLoginModeMock.mock.calls or
.mock.lastCall and ensure no displayed labels/choices include that email), while
keeping the existing assertions that fetchCodexQuotaSnapshotMock and
saveQuotaCacheMock were not called; reference promptLoginModeMock and
runCodexMultiAuthCli to locate where to add the new assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/codex-manager.ts`:
- Around line 2473-2475: Add vitest regression tests that exercise the non-JSON
code paths by running the CLI handlers for "codex auth forecast --live" and
"codex auth fix --live" (the same CLI entrypoints covered by
test/codex-manager-cli.test.ts) and assert they succeed under intermittent
Windows-style rename failures and concurrent save pressure; specifically, mock
the filesystem rename/write used by saveQuotaCache to throw EBUSY/EPERM on some
attempts and succeed on retries, spawn concurrent callers to trigger concurrent
save attempts, and verify the code uses workingQuotaCache and completes without
crashing. Place these new tests alongside test/quota-cache.test.ts and
test/storage.test.ts, reference the saveQuotaCache function and the CLI handlers
for auth forecast/fix in assertions, and ensure the tests simulate both
single-threaded retry and concurrent contention scenarios (including 429-like
retry behaviour) to prove the branches under Windows rename contention.

In `@test/codex-manager-cli.test.ts`:
- Around line 3051-3123: The test relies on ordered mock responses from
fetchCodexQuotaSnapshotMock but never asserts which workspace/token each call
used, allowing a regression where both probes target the same workspace; update
the test around runCodexMultiAuthCli to include explicit toHaveBeenNthCalledWith
assertions on fetchCodexQuotaSnapshotMock for call 1 and call 2 verifying the
expected probe inputs (e.g., that the first call was invoked for
"workspace-alpha" with its token and the second for "workspace-beta" with its
token), keeping the existing saveQuotaCacheMock and promptLoginModeMock
assertions intact and ensuring the checks use Vitest matchers so the test
deterministically proves the two live probes remain distinct.

In `@test/quota-cache.test.ts`:
- Around line 178-241: The test currently only checks final file validity but
must also assert that no save hit the warning path in lib/quota-cache.ts (the
warning logged around the retry/failure handling at the saveQuotaCache path).
Update the test to mock the logger module (../lib/logger.js) with vitest
(vi.mock) and spy on the logWarn export before importing
saveQuotaCache/getQuotaCachePath/loadQuotaCache, then after the concurrent
Promise.all call assert that the spy was not called (logWarn stayed cold);
restore/mock cleanup in the finally block to keep the test deterministic.

---

Outside diff comments:
In `@test/codex-manager-cli.test.ts`:
- Around line 5052-5345: Add two new vitest tests in
test/codex-manager-cli.test.ts that mirror the existing "recomputes live quota
fallback state after refresh changes a shared-workspace email" and "recomputes
live quota fallback state after refresh changes accountId for the same email"
cases but call runCodexMultiAuthCli(["auth","check","--live","--json"]) instead
of "fix"; reproduce the same mock setups for loadAccountsMock,
loadQuotaCacheMock, queuedRefreshMock, accountsModule.extractAccountId,
accountsModule.extractAccountEmail, fetchCodexQuotaSnapshotMock, and spies
(console.log) and assert the same outcomes (exit code 0, queuedRefreshMock
called once, fetchCodexQuotaSnapshotMock twice, saveQuotaCacheMock and
saveAccountsMock called with the expected byAccountId/byEmail shape and
account/email changes, and that the JSON reports contain two "healthy" reports)
to ensure deterministic coverage of both refreshed fallback branches for the
"auth check" path.
- Around line 3164-3229: The test seeds a stale byEmail entry but never asserts
the login menu didn't show that stale email; update the test around
runCodexMultiAuthCli to explicitly assert that the mocked menu
(promptLoginModeMock) was not passed any choices containing "owner@example.com"
(i.e., inspect promptLoginModeMock.mock.calls or .mock.lastCall and ensure no
displayed labels/choices include that email), while keeping the existing
assertions that fetchCodexQuotaSnapshotMock and saveQuotaCacheMock were not
called; reference promptLoginModeMock and runCodexMultiAuthCli to locate where
to add the new assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f55b8ffb-57b4-445c-873f-01cf6ceb0ab2

📥 Commits

Reviewing files that changed from the base of the PR and between c5d1b85 and 252ba8a.

📒 Files selected for processing (3)
  • lib/codex-manager.ts
  • test/codex-manager-cli.test.ts
  • test/quota-cache.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (2)
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/codex-manager-cli.test.ts
  • test/quota-cache.test.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/codex-manager.ts
🔇 Additional comments (3)
lib/codex-manager.ts (3)

448-489: good fallback-state guardrails for shared emails.

this correctly prevents unsafe by-email reuse when multiple workspace identities share one email, while still allowing safe fallback for a single-account email path. nice direction for the #121 objective in lib/codex-manager.ts:448-489.


1752-1754: good recompute on identity mutation during auth rotation.

rebuilding fallback state immediately after email/accountid mutations avoids stale key decisions in the same pass. this is the right fix shape for refresh-time identity drift in lib/codex-manager.ts:1752-1754 and lib/codex-manager.ts:3213-3215.

Also applies to: 3213-3215


1634-1635: working cache isolation is correctly threaded.

cloning into workingQuotaCache before live updates is a solid isolation boundary and avoids mutating the loaded cache object on failed saves across health/forecast/fix flows in lib/codex-manager.ts:1634-1635, lib/codex-manager.ts:2297-2298, and lib/codex-manager.ts:3088-3089.

Also applies to: 2297-2298, 3088-3089

@ndycode
Copy link
Owner Author

ndycode commented Mar 18, 2026

@greptileai

@ndycode
Copy link
Owner Author

ndycode commented Mar 18, 2026

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 18, 2026

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/codex-manager-cli.test.ts (1)

5833-5938: ⚠️ Potential issue | 🟡 Minor

restore mocks and consider adding probe input binding assertions.

test/codex-manager-cli.test.ts:5834-5846 - missing mock restoration for extractAccountId and extractAccountEmail.

additionally, consider adding toHaveBeenNthCalledWith assertions for fetchCodexQuotaSnapshotMock to explicitly bind each probe to its workspace-alpha/workspace-beta input, similar to test/codex-manager-cli.test.ts:3434-3443. this guards against regressions where both probes accidentally hit the same workspace.

as per coding guidelines test/**: tests must stay deterministic and demand regression cases that reproduce concurrency bugs.

proposed fix for mock restoration
 		expect(
 			payload.reports.filter((report) => report.outcome === "healthy"),
 		).toHaveLength(2);
+		vi.mocked(accountsModule.extractAccountId).mockImplementation(() => "acc_test");
+		vi.mocked(accountsModule.extractAccountEmail).mockImplementation(() => undefined);
 	});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/codex-manager-cli.test.ts` around lines 5833 - 5938, The test leaks
mocked implementations for accountsModule.extractAccountId and
accountsModule.extractAccountEmail; restore them after the scenario and add
explicit probe-input binding assertions: call
vi.mocked(accountsModule.extractAccountId).mockRestore() and
vi.mocked(accountsModule.extractAccountEmail).mockRestore() at the end of the
test (or in a finally/afterEach), and add toHaveBeenNthCalledWith checks on
fetchCodexQuotaSnapshotMock (e.g., assert the 1st call used workspace-alpha
probe/input and the 2nd used workspace-beta) to ensure each probe targeted the
intended account; reference the mocked symbols extractAccountId,
extractAccountEmail and fetchCodexQuotaSnapshotMock when locating where to add
restoration and toHaveBeenNthCalledWith assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/codex-manager-cli.test.ts`:
- Around line 3648-3713: The test replaces accountsModule.extractAccountId but
never restores it, leaving global test state mutated; after the assertions add a
cleanup to restore the original implementation — either call
vi.mocked(accountsModule.extractAccountId).mockRestore() (or .mockReset() if
mockRestore isn't available) or run vi.resetAllMocks()/vi.restoreAllMocks() at
the end of the test so extractAccountId from the imported accountsModule is
returned to its original behavior.
- Around line 3549-3586: The test contains dead setup for
fetchCodexQuotaSnapshotMock (the .mockResolvedValueOnce(...) chain) but later
asserts fetchCodexQuotaSnapshotMock was not called, so remove the unnecessary
mockResolvedValueOnce setup to clarify intent; also restore the previously
mocked extractAccountId (call extractAccountIdMock.mockRestore() or
jest.restoreMockFor('extractAccountId') depending on how it was mocked) before
importing runCodexMultiAuthCli so the real extractAccountId behavior is used;
keep existing references to promptLoginModeMock and saveQuotaCacheMock
assertions intact.
- Around line 1494-1561: The test sets custom implementations for
accountsModule.extractAccountId and accountsModule.extractAccountEmail but never
restores them, which can leak state to later tests; after the assertions at the
end of this test, call vi.mocked(accountsModule.extractAccountId).mockRestore()
and vi.mocked(accountsModule.extractAccountEmail).mockRestore() (or the
equivalent restore/reset used elsewhere in this file) to revert the mocks to
their original behavior so other tests aren’t affected.
- Around line 1619-1706: The test sets custom mocks for
accountsModule.extractAccountId and accountsModule.extractAccountEmail but
doesn’t restore them; after the assertions at the end of this test, call
vi.mocked(accountsModule.extractAccountId).mockRestore() and
vi.mocked(accountsModule.extractAccountEmail).mockRestore() (or
vi.restoreAllMocks() if you prefer) to restore original implementations so
subsequent tests aren’t affected.
- Around line 5675-5774: The test stubs for accountsModule.extractAccountId and
accountsModule.extractAccountEmail are not being restored, so add mock
restoration at the end of the test (after the assertions) by calling the
appropriate restore on the vi-mocked functions (restore the mocks created via
vi.mocked(accountsModule.extractAccountId) and
vi.mocked(accountsModule.extractAccountEmail)) so the mocks do not leak into
other tests.

---

Outside diff comments:
In `@test/codex-manager-cli.test.ts`:
- Around line 5833-5938: The test leaks mocked implementations for
accountsModule.extractAccountId and accountsModule.extractAccountEmail; restore
them after the scenario and add explicit probe-input binding assertions: call
vi.mocked(accountsModule.extractAccountId).mockRestore() and
vi.mocked(accountsModule.extractAccountEmail).mockRestore() at the end of the
test (or in a finally/afterEach), and add toHaveBeenNthCalledWith checks on
fetchCodexQuotaSnapshotMock (e.g., assert the 1st call used workspace-alpha
probe/input and the 2nd used workspace-beta) to ensure each probe targeted the
intended account; reference the mocked symbols extractAccountId,
extractAccountEmail and fetchCodexQuotaSnapshotMock when locating where to add
restoration and toHaveBeenNthCalledWith assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fbbfcbe7-d0fa-431c-8016-6f5fa159fff6

📥 Commits

Reviewing files that changed from the base of the PR and between 252ba8a and c073b9c.

📒 Files selected for processing (3)
  • lib/codex-manager.ts
  • test/codex-manager-cli.test.ts
  • test/quota-cache.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (2)
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/codex-manager-cli.test.ts
  • test/quota-cache.test.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/codex-manager.ts
🔇 Additional comments (21)
lib/codex-manager.ts (12)

443-475: lgtm on the fallback state builder.

the buildQuotaEmailFallbackState function correctly handles undefined/empty emails by skipping them via normalizeQuotaEmail. the distinctAccountIds set properly tracks unique accountIds per email to detect multi-workspace collisions.


477-489: core logic for issue #121 looks solid.

hasSafeQuotaEmailFallback correctly returns false when distinctAccountIds.size > 1, which is the key guard preventing multiple workspaces sharing an email from collapsing into one cached quota entry. the matchingCount === 1 check ensures we only use email fallback when there's exactly one account with that email.


562-585: email fallback guard is correct.

the hasSafeQuotaEmailFallback check at line 579 prevents returning stale email-keyed entries when multiple workspaces share the same email. callers in toExistingAccountInfo, runHealthCheck, and runFix properly pass pre-computed emailFallbackState to avoid repeated rebuilds.


611-632: pruning logic handles stale byEmail entries correctly.

lines 627-630 delete cache.byEmail[email] when either:

  1. the account now has a unique accountId (prefer byAccountId), or
  2. the email fallback is no longer safe (multi-workspace conflict)

this ensures stale email-keyed cache entries don't persist after identity resolution improves.


634-641: shallow clone is sufficient here.

the comment correctly notes that entries are replaced not mutated. this isolates workingQuotaCache from the original quotaCache so failed saves don't corrupt loaded state. see usage at lib/codex-manager.ts:1658, lib/codex-manager.ts:2329, lib/codex-manager.ts:3120.


643-663: prune function correctly cleans up after identity mutations.

pruneUnsafeQuotaEmailCacheEntry is called at lib/codex-manager.ts:1780 and lib/codex-manager.ts:3249 after accountIdentityChanged is detected. the accounts.some() loop ensures we only delete when no account still qualifies for safe email fallback.


700-706: canStore guard avoids wasted probes.

the guard at lines 702-706 correctly skips probing when neither hasUniqueQuotaAccountId nor hasSafeQuotaEmailFallback is true. this prevents fetching quota that can't be cached, aligning with the comment at lines 700-701.


768-820: isolation pattern in refreshQuotaCacheForMenu is correct.

the function clones at line 779, mutates nextCache, and saves at line 816. the original cache param is never mutated. returning nextCache at line 819 ensures callers get the updated state.


1777-1786: fallback state is rebuilt after identity mutation.

this addresses the past review concern about stale quotaEmailFallbackState. when accountIdentityChanged is true, line 1778 rebuilds the state before calling pruneUnsafeQuotaEmailCacheEntry. subsequent updateQuotaCacheForAccount calls at line 1806-1813 receive the fresh state via quotaEmailFallbackState ?? undefined.


2338-2341: single fallback state build is correct for runForecast.

unlike runHealthCheck and runFix, runForecast doesn't persist identity changes back to storage.accounts. the refresh results at lines 2357-2367 update only local probeAccessToken/probeAccountId, not the account objects in storage. so the fallback state computed once at line 2338 remains valid throughout.


3246-3255: fallback state rebuild in runFix matches runHealthCheck pattern.

line 3247 rebuilds quotaEmailFallbackState after identity mutation, and line 3249-3254 prunes stale email entries. this is consistent with the runHealthCheck pattern at lib/codex-manager.ts:1777-1786.


959-967: single fallback state build is correct for read-only iteration.

toExistingAccountInfo doesn't mutate accounts, so building emailFallbackState once at line 959 and passing it to all getQuotaCacheEntryForAccount calls is efficient and correct.

test/quota-cache.test.ts (3)

6-13: helper is clean and type-safe.

makeErrnoError correctly constructs errno-style exceptions matching the RETRYABLE_FS_CODES set in lib/quota-cache.ts:35. the type constraint ensures only valid retry codes are used in tests.


178-250: concurrent save test addresses past review concern.

the logger mock at lines 181-183 and assertion at line 242 address the previous review comment about verifying no saves hit the warning path. the test correctly exercises:

  1. concurrent writes (4 parallel saves at line 230)
  2. windows-style errors (EBUSY/EPERM alternating at lines 214-219)
  3. atomic file integrity (JSON parse assertion at lines 234-239)
  4. temp file cleanup (line 245)

the fixed error schedule via retryableAttempts map makes the test deterministic.


229-241: assertion attempts > 4 correctly validates retry behavior.

with 4 concurrent saves and errors on attempts 1, 2, 4, 5, each failing save must retry. the toBeGreaterThan(4) assertion confirms retry logic executed. the interleaved execution order varies, but the assertion accounts for this by checking minimum expected attempts rather than exact count.

test/codex-manager-cli.test.ts (6)

570-631: lgtm - ebusy regression coverage added.

test covers lib/codex-manager.ts live forecast save failure with EBUSY errno, verifying original quota cache object stays unmutated. assertions are complete for call count and payload shape.


3357-3480: lgtm - proper probe binding assertions present.

test/codex-manager-cli.test.ts:3434-3443 uses toHaveBeenNthCalledWith to explicitly verify which workspace/token each live probe targeted. this addresses the past concern about ensuring probes stay distinct per workspace.


2935-3036: lgtm - good coverage for multi-workspace same-email oauth flows.

test correctly verifies that distinct same-email workspaces (workspace-alpha, workspace-beta) are preserved during oauth login when refresh token is reused. uses mockImplementationOnce pattern for test-scoped mocks.


5159-5196: lgtm - lockout prevention regression added.

test/codex-manager-cli.test.ts:5159-5196 covers the edge case where the last enabled account fails refresh but must stay enabled to prevent lockout. assertion at line 5187-5188 explicitly checks enabled state and line 5194-5195 verifies the warning message.


5283-5329: lgtm - ebusy regression for live fix account save failure.

test verifies original quota cache object stays unmutated when live fix account save fails with EBUSY. assertion at line 5324-5327 checks reference equality. note that saveQuotaCacheMock is expected NOT to be called since the failure happens before quota cache save.


5543-5616: ⚠️ Potential issue | 🟡 Minor

restore extractaccountid and extractaccountemail mocks at test end.

test/codex-manager-cli.test.ts:5544-5557 - same pattern as other tests. add mock restoration after assertions.

proposed fix
 		expect(
 			payload.reports.filter((report) => report.outcome === "healthy"),
 		).toHaveLength(2);
+		vi.mocked(accountsModule.extractAccountId).mockImplementation(() => "acc_test");
+		vi.mocked(accountsModule.extractAccountEmail).mockImplementation(() => undefined);
 	});
			> Likely an incorrect or invalid review comment.

@ndycode ndycode merged commit b918aac into main Mar 18, 2026
2 checks passed
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.

[bug] Seem like the feature of account got muti team did not working right ?

1 participant